WordPress.org

Make WordPress Core

Changeset 25841


Ignore:
Timestamp:
10/18/13 16:29:16 (6 months ago)
Author:
nacin
Message:

Notify administrators of successful, failed, and pending core updates.

Blocks future background updates after critical failures, but allow retries in certain situations. More in the ticket.

fixes #10787.

Location:
trunk/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/about.php

    r25840 r25841  
    5656                $upgrader = new WP_Automatic_Updater; 
    5757                $future_minor_update = (object) array( 
    58                     'current'       => $wp_version . '.1-about.php', 
    59                     'version'       => $wp_version . '.1-about.php', 
     58                    'current'       => $wp_version . '.1.next.minor', 
     59                    'version'       => $wp_version . '.1.next.minor', 
    6060                    'php_version'   => $required_php_version, 
    6161                    'mysql_version' => $required_mysql_version, 
  • trunk/src/wp-admin/includes/class-wp-upgrader.php

    r25837 r25841  
    14381438            return false; 
    14391439 
     1440        $failure_data = get_site_option( 'auto_core_update_failed' ); 
     1441        if ( $failure_data ) { 
     1442            // If this was a critical update failure, cannot update. 
     1443            if ( ! empty( $failure_data['critical'] ) ) 
     1444                return false; 
     1445 
     1446            // Don't claim we can update on update-core.php if we have a non-critical failure logged. 
     1447            if ( $wp_version == $failure_data['current'] && false !== strpos( $wp_version, '.1.next.minor' ) ) 
     1448                return false; 
     1449 
     1450            // Cannot update if we're retrying the same A to B update that caused a non-critical failure. 
     1451            // Some non-critical failures do allow retries, like download_failed. 
     1452            // 3.7.1 => 3.7.2 resulted in files_not_writable, if we are still on 3.7.1 and still trying to update to 3.7.2. 
     1453            if ( empty( $failure_data['retry'] ) && $wp_version == $failure_data['current'] && $offered_ver == $failure_data['attempted'] ) 
     1454                return false; 
     1455        } 
     1456 
    14401457        // 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2 
    14411458        if ( $current_is_development_version ) { 
     
    16271644        // And does the user / plugins want it? 
    16281645        // Plugins may filter on 'auto_update_plugin', and check the 2nd param, $item, to only enable it for certain Plugins/Themes 
    1629         if ( ! apply_filters( 'auto_update_' . $type, $update, $item ) ) 
     1646        $update = apply_filters( 'auto_update_' . $type, $update, $item ); 
     1647 
     1648        if ( ! $update ) { 
     1649 
     1650            // See if we need to notify users of a core update. 
     1651            if ( 'core' == $type && ! empty( $item->notify_email ) ) { 
     1652                $notify      = true; 
     1653                $notified    = get_site_option( 'auto_core_update_notified' ); 
     1654 
     1655                // Don't notify if we've already notified the same email address of the same version. 
     1656                if ( $notified && $notified['email'] == get_site_option( 'admin_email' ) && $notified['version'] == $item->current ) 
     1657                    return false; 
     1658 
     1659                $this->send_email( 'manual', $item ); 
     1660            } 
     1661 
    16301662            return false; 
     1663        } 
    16311664 
    16321665        // If it's a core update, are we actually compatible with its requirements? 
     
    17281761     */ 
    17291762    function run() { 
    1730         global $wpdb; 
     1763        global $wpdb, $wp_version; 
    17311764 
    17321765        if ( ! is_main_network() || ! is_main_site() ) 
     
    18311864        } 
    18321865 
    1833         $this->send_debug_email(); 
     1866        // Send debugging email to all development installs. 
     1867        if ( ! empty( $this->update_results ) ) { 
     1868            $development_version = false !== strpos( $wp_version, '-' ); 
     1869            if ( apply_filters( 'automatic_updates_send_debug_email', $development_version ) ) 
     1870                $this->send_debug_email(); 
     1871 
     1872            if ( ! empty( $this->update_results['core'] ) ) 
     1873                $this->after_core_update( $this->update_results['core'][0] ); 
     1874        } 
    18341875 
    18351876        // Clear the lock 
     
    18371878    } 
    18381879 
     1880    /** 
     1881     * If we tried to perform a core update, check if we should send an email, 
     1882     * and if we need to avoid processing future updates. 
     1883     */ 
     1884    protected function after_core_update( $update_result ) { 
     1885        global $wp_version; 
     1886 
     1887        $core_update = $update_result->item; 
     1888        $result      = $update_result->result; 
     1889 
     1890        if ( ! is_wp_error( $result ) ) { 
     1891            $this->send_email( 'success', $core_update ); 
     1892            return; 
     1893        } 
     1894 
     1895        $error_code = $result->get_error_code(); 
     1896 
     1897        // Any of these WP_Error codes are critical failures, as in they occurred after we started to copy core files. 
     1898        // We should not try to perform a background update again until there is a successful one-click update performed by the user. 
     1899        $critical = false; 
     1900        if ( $error_code === 'disk_full' || false !== strpos( $error_code, '__copy_dir' ) ) { 
     1901            $critical = true; 
     1902        } elseif ( $error_code === 'rollback_was_required' ) { 
     1903            $error_data = $result->get_error_data(); 
     1904            if ( is_wp_error( $error_data['rollback'] ) ) 
     1905                $critical = true; 
     1906        } elseif ( false !== strpos( $error_code, 'do_rollback' ) ) { 
     1907            $critical = true; 
     1908        } 
     1909 
     1910        if ( $critical ) { 
     1911            update_site_option( 'auto_core_update_failed', array( 
     1912                'attempted'  => $core_update->current, 
     1913                'current'    => $wp_version, 
     1914                'error_code' => $error_code, 
     1915                'error_data' => $result->get_error_data(), 
     1916                'timestamp'  => time(), 
     1917                'critical'   => true, 
     1918            ) ); 
     1919            $this->send_email( 'critical', $core_update, $result ); 
     1920            return; 
     1921        } 
     1922 
     1923        /* 
     1924         * Any other WP_Error code (like download_failed or files_not_writable) occurs before 
     1925         * we tried to copy over core files. Thus, the failures are early and graceful. 
     1926         * 
     1927         * We should avoid trying to perform a background update again for the same version. 
     1928         * But we can try again if another version is released. 
     1929         * 
     1930         * For certain 'transient' failures, like download_failed, we should allow retries. 
     1931         * In fact, let's schedule a special update for an hour from now. (It's possible 
     1932         * the issue could actually be on WordPress.org's side.) If that one fails, then email. 
     1933         */ 
     1934        $send = true; 
     1935        $transient_failures = array( 'incompatible_archive', 'download_failed', 'insane_distro' ); 
     1936        if ( in_array( $error_code, $transient_failures ) && ! get_site_option( 'auto_core_update_failed' ) ) { 
     1937            wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_maybe_auto_update' ); 
     1938            $send = false; 
     1939        } 
     1940 
     1941        $n = get_site_option( 'auto_core_update_notified' ); 
     1942        // Don't notify if we've already notified the same email address of the same version of the same notification type. 
     1943        if ( $n && 'fail' == $n['type'] && $n['email'] == get_site_option( 'admin_email' ) && $n['version'] == $core_update->current ) 
     1944            $send = false; 
     1945 
     1946        update_site_option( 'auto_core_update_failed', array( 
     1947            'attempted'  => $core_update->current, 
     1948            'current'    => $wp_version, 
     1949            'error_code' => $error_code, 
     1950            'error_data' => $result->get_error_data(), 
     1951            'timestamp'  => time(), 
     1952            'retry'      => in_array( $error_code, $transient_failures ), 
     1953        ) ); 
     1954 
     1955        if ( $send ) 
     1956            $this->send_email( 'fail', $core_update, $result ); 
     1957    } 
     1958 
    18391959    protected function send_email( $type, $core_update, $result = null ) { 
     1960        update_site_option( 'auto_core_update_notified', array( 
     1961            'type'      => $type, 
     1962            'email'     => get_site_option( 'admin_email' ), 
     1963            'version'   => $core_update->current, 
     1964            'timestamp' => time(), 
     1965        ) ); 
     1966 
    18401967        if ( ! apply_filters( 'automatic_updates_send_email', true, $type, $core_update, $result ) ) 
    18411968            return; 
     
    19182045            $body .= __( 'We have some data that describes the error your site encountered.' ); 
    19192046            $body .= ' ' . __( 'Your hosting company, support forum volunteers, or a friendly developer may be able to use this information to help you:' ); 
    1920             $body .= "\n" . sprintf( __( "Error code: %s" ), $result->get_error_code() ); 
    1921             $body .= "\n" . $result->get_error_message(); 
    1922             $body .= "\n" . implode( ', ', (array) $result->get_error_data() ); 
     2047            $body .= "\n\n" . sprintf( __( "Error code: %s" ), $result->get_error_code() ); 
     2048            if ( $result->get_error_message() ) 
     2049                $body .= "\n" . $result->get_error_message(); 
     2050            if ( $result->get_error_data() ) 
     2051                $body .= "\n" . implode( ', ', (array) $result->get_error_data() ); 
    19232052            $body .= "\n"; 
    19242053        } 
     
    19342063 
    19352064    protected function send_debug_email() { 
    1936         if ( empty( $this->update_results ) ) 
    1937             return; 
    1938  
    19392065        $update_count = 0; 
    19402066        foreach ( $this->update_results as $type => $updates ) 
     
    19862112            $body[] = '============='; 
    19872113            $body[] = ''; 
    1988             $body[] = 'If you think these failures might be due to a bug in WordPress 3.7, could you report it?'; 
     2114            $body[] = 'This debugging email is sent when you are using a development version of WordPress.'; 
     2115            $body[] = ''; 
     2116            $body[] = 'If you think these failures might be due to a bug in WordPress, could you report it?'; 
    19892117            $body[] = ' * Open a thread in the support forums: http://wordpress.org/support/forum/alphabeta'; 
    19902118            $body[] = " * Or, if you're comfortable writing a bug report: http://core.trac.wordpress.org/"; 
  • trunk/src/wp-admin/includes/update-core.php

    r25831 r25841  
    898898    do_action( '_core_updated_successfully', $wp_version ); 
    899899 
     900    // Clear the option that blocks auto updates after failures, now that we've been successful. 
     901    delete_site_option( 'auto_core_update_failed' ); 
     902 
    900903    return $wp_version; 
    901904} 
  • trunk/src/wp-admin/update-core.php

    r25835 r25841  
    151151            $upgrader = new WP_Automatic_Updater; 
    152152            $future_minor_update = (object) array( 
    153                 'current'       => $wp_version . '.1-update-core.php', 
    154                 'version'       => $wp_version . '.1-update-core.php', 
     153                'current'       => $wp_version . '.1.next.minor', 
     154                'version'       => $wp_version . '.1.next.minor', 
    155155                'php_version'   => $required_php_version, 
    156156                'mysql_version' => $required_mysql_version, 
  • trunk/src/wp-includes/update.php

    r25835 r25841  
    132132        } 
    133133        $offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale', 
    134             'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version' ), '' ) ); 
     134            'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email' ), '' ) ); 
    135135    } 
    136136 
Note: See TracChangeset for help on using the changeset viewer.