How to hook into wordpress upgrade procedure for a custom theme

Have you checked for hooks inside class-theme-upgrader ?

File: wp-admin/includes/class-theme-upgrader.php
233:    /**
234:     * Upgrade a theme.
235:     *
236:     * @since 2.8.0
237:     * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
238:     * @access public
239:     *
240:     * @param string $theme The theme slug.
241:     * @param array  $args {
242:     *     Optional. Other arguments for upgrading a theme. Default empty array.
243:     *
244:     *     @type bool $clear_update_cache Whether to clear the update cache if successful.
245:     *                                    Default true.
246:     * }
247:     * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise.
248:     */
249:    public function upgrade( $theme, $args = array() ) {
250: 
251:        $defaults = array(
252:            'clear_update_cache' => true,
253:        );
254:        $parsed_args = wp_parse_args( $args, $defaults );
255: 
256:        $this->init();
257:        $this->upgrade_strings();
258: 
259:        // Is an update available?
260:        $current = get_site_transient( 'update_themes' );
261:        if ( !isset( $current->response[ $theme ] ) ) {
262:            $this->skin->before();
263:            $this->skin->set_result(false);
264:            $this->skin->error( 'up_to_date' );
265:            $this->skin->after();
266:            return false;
267:        }
268: 
269:        $r = $current->response[ $theme ];
270: 
271:        add_filter('upgrader_pre_install', array($this, 'current_before'), 10, 2);
272:        add_filter('upgrader_post_install', array($this, 'current_after'), 10, 2);
273:        add_filter('upgrader_clear_destination', array($this, 'delete_old_theme'), 10, 4);
274:        if ( $parsed_args['clear_update_cache'] ) {
275:            // Clear cache so wp_update_themes() knows about the new theme.
276:            add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
277:        }
278: 
279:        $this->run( array(
280:            'package' => $r['package'],
281:            'destination' => get_theme_root( $theme ),
282:            'clear_destination' => true,
283:            'clear_working' => true,
284:            'hook_extra' => array(
285:                'theme' => $theme,
286:                'type' => 'theme',
287:                'action' => 'update',
288:            ),
289:        ) );
290: 
291:        remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
292:        remove_filter('upgrader_pre_install', array($this, 'current_before'));
293:        remove_filter('upgrader_post_install', array($this, 'current_after'));
294:        remove_filter('upgrader_clear_destination', array($this, 'delete_old_theme'));
295: 
296:        if ( ! $this->result || is_wp_error($this->result) )
297:            return $this->result;
298: 
299:        wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
300: 
301:        return true;
302:    }