Make WordPress Core

Changeset 58128

Timestamp:
05/10/2024 11:46:51 AM (3 months ago)
Author:
johnbillion
Message:

Upgrade/Install: Automatically roll back to the previous version when an automatic plugin update results in a fatal error on the front end of the site.

This builds on the temporary backup system introduced in 6.3 to allow automatic updates to benefit from fatal error protection. A loopback request is performed to the home page of the site and the plugin is rolled back to its backed up version if a fatal error is observed.

For debugging and observability during beta, this change includes several calls to error_log() during the upgrade and rollback stages. These calls can be removed or placed behind a flag once we're ready for RC1.

Props costdev, johnbillion, mukesh27, afragen, audrasjb, justlevine, kirasong, peterwilsoncc

Fixes #58281

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-automatic-updater.php

    r56549 r58128  
    447447        }
    448448
     449
     450
     451
     452
     453
     454
     455
     456
     457
     458
     459
     460
     461
     462
     463
     464
     465
     466
     467
     468
     469
     470
     471
    449472        // Boom, this site's about to get a whole new splash of paint!
    450473        $upgrade_result = $upgrader->upgrade(
     
    461484        );
    462485
     486
     487
     488
     489
     490
     491
     492
     493
     494
     495
     496
    463497        // If the filesystem is unavailable, false is returned.
    464498        if ( false === $upgrade_result ) {
     
    487521        }
    488522
     523
     524
     525
     526
     527
     528
     529
     530
     531
     532
     533
     534
     535
     536
     537
     538
     539
     540
     541
     542
     543
     544
     545
     546
     547
     548
     549
     550
     551
     552
     553
     554
     555
     556
     557
     558
     559
     560
     561
     562
     563
     564
     565
     566
     567
     568
     569
     570
     571
     572
     573
     574
     575
     576
     577
     578
     579
     580
     581
     582
     583
     584
     585
     586
     587
     588
     589
     590
     591
     592
     593
     594
     595
     596
     597
     598
     599
     600
     601
     602
     603
     604
     605
     606
     607
     608
    489609        $this->update_results[ $type ][] = (object) array(
    490610            'item'     => $item,
     
    515635        }
    516636
     637
     638
    517639        // Don't automatically run these things, as we'll handle it ourselves.
    518640        remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
     
    525647        $plugin_updates = get_site_transient( 'update_plugins' );
    526648        if ( $plugin_updates && ! empty( $plugin_updates->response ) ) {
     649
     650
    527651            foreach ( $plugin_updates->response as $plugin ) {
    528652                $this->update( 'plugin', $plugin );
    529653            }
     654
    530655            // Force refresh of plugin update information.
    531656            wp_clean_plugins_cache();
     657
     658
    532659        }
    533660
     
    536663        $theme_updates = get_site_transient( 'update_themes' );
    537664        if ( $theme_updates && ! empty( $theme_updates->response ) ) {
     665
     666
    538667            foreach ( $theme_updates->response as $theme ) {
    539668                $this->update( 'theme', (object) $theme );
     
    541670            // Force refresh of theme update information.
    542671            wp_clean_themes_cache();
    543         }
     672
     673            error_log( '  Automatic theme updates complete.' );
     674        }
     675
     676        error_log( 'Automatic updates complete.' );
    544677
    545678        // Next, process any core update.
     
    11641297            // List failed plugin updates.
    11651298            if ( ! empty( $failed_updates['plugin'] ) ) {
    1166                 $body[] = __( 'These plugins failed to update:' );
     1299                $body[] = __( 'The' );
    11671300
    11681301                foreach ( $failed_updates['plugin'] as $item ) {
     
    15521685        wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
    15531686    }
     1687
     1688
     1689
     1690
     1691
     1692
     1693
     1694
     1695
     1696
     1697
     1698
     1699
     1700
     1701
     1702
     1703
     1704
     1705
     1706
     1707
     1708
     1709
     1710
     1711
     1712
     1713
     1714
     1715
     1716
     1717
     1718
     1719
     1720
     1721
     1722
     1723
     1724
     1725
     1726
     1727
     1728
     1729
     1730
     1731
     1732
     1733
     1734
     1735
     1736
     1737
     1738
     1739
     1740
     1741
     1742
     1743
     1744
     1745
     1746
     1747
     1748
     1749
     1750
     1751
     1752
     1753
     1754
     1755
     1756
     1757
     1758
     1759
     1760
     1761
     1762
     1763
     1764
     1765
     1766
    15541767}
  • trunk/src/wp-admin/includes/class-wp-upgrader.php

    r58105 r58128  
    902902
    903903        if ( is_wp_error( $result ) ) {
     904
    904905            if ( ! empty( $options['hook_extra']['temp_backup'] ) ) {
    905906                $this->temp_restores[] = $options['hook_extra']['temp_backup'];
     
    910911                 * so in case the failure was due to a PHP timeout,
    911912                 * it will still be able to properly restore the previous version.
     913
     914
     915
     916
    912917                 */
    913                 add_action( 'shutdown', array( $this, 'restore_temp_backup' ) );
     918                add_action( 'shutdown', array( $this, 'restore_temp_backup' ) );
    914919            }
    915920            $this->skin->error( $result );
     
    984989    public function maintenance_mode( $enable = false ) {
    985990        global $wp_filesystem;
     991
     992
     993
     994
     995
     996
    986997        $file = $wp_filesystem->abspath() . '.maintenance';
    987998        if ( $enable ) {
    988             $this->skin->feedback( 'maintenance_start' );
     999            if ( ! wp_doing_cron() ) {
     1000                $this->skin->feedback( 'maintenance_start' );
     1001            }
    9891002            // Create maintenance file to signal that we are upgrading.
    9901003            $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
     
    9921005            $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE );
    9931006        } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) {
    994             $this->skin->feedback( 'maintenance_end' );
     1007            if ( ! wp_doing_cron() ) {
     1008                $this->skin->feedback( 'maintenance_end' );
     1009            }
    9951010            $wp_filesystem->delete( $file );
    9961011        }
     
    11341149     *
    11351150     * @since 6.3.0
     1151
    11361152     *
    11371153     * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
    11381154     *
     1155
     1156
     1157
     1158
     1159
     1160
     1161
     1162
     1163
     1164
     1165
    11391166     * @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
    11401167     */
    1141     public function restore_temp_backup() {
     1168    public function restore_temp_backup() {
    11421169        global $wp_filesystem;
    11431170
    11441171        $errors = new WP_Error();
    11451172
    1146         foreach ( $this->temp_restores as $args ) {
     1173        if ( empty( $temp_backups ) ) {
     1174            $temp_backups = $this->temp_restores;
     1175        }
     1176
     1177        foreach ( $temp_backups as $args ) {
    11471178            if ( empty( $args['slug'] ) || empty( $args['src'] ) || empty( $args['dir'] ) ) {
    11481179                return false;
     
    11871218     *
    11881219     * @since 6.3.0
     1220
    11891221     *
    11901222     * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
    11911223     *
     1224
     1225
     1226
     1227
     1228
     1229
     1230
     1231
     1232
     1233
     1234
    11921235     * @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
    11931236     */
    1194     public function delete_temp_backup() {
     1237    public function delete_temp_backup() {
    11951238        global $wp_filesystem;
    11961239
    11971240        $errors = new WP_Error();
    11981241
    1199         foreach ( $this->temp_backups as $args ) {
     1242        if ( empty( $temp_backups ) ) {
     1243            $temp_backups = $this->temp_backups;
     1244        }
     1245
     1246        foreach ( $temp_backups as $args ) {
    12001247            if ( empty( $args['slug'] ) || empty( $args['dir'] ) ) {
    12011248                return false;
  • trunk/src/wp-includes/load.php

    r57831 r58128  
    419419    if ( ( time() - $upgrading ) >= 10 * MINUTE_IN_SECONDS ) {
    420420        return false;
     421
     422
     423
     424
     425
     426
     427
     428
     429
     430
    421431    }
    422432
Note: See TracChangeset for help on using the changeset viewer.