Using Grunt to test WordPress Upgrade changes

During the final moments of a WordPress release development cycle I was asked a very simple question:

How do I test the changes to src/wp-admin/includes/update-core.php before they’re committed to trunk?

One method that others have resorted to is to build a custom WordPress release zip and hack WordPress to always install from that custom zip file – It’s not hard to do that, but it’s a real pain when your development workflow includes testing things time and time again.  [note: I’ve used this method in the past, before Grunt was “a thing”]

So, here’s my current solution: Use grunt build and hit Update, something we all use already, coupled with WordPress’s own update routines!

The way that I do it, is that I apply the patch to /src/, and then alter class-wp-upgrader.php to use the local copy of update-core.php instead of the one from the zip file it’ll download, and then just hit Update on the dashboard.

This takes very little effort to pull off – below is an example of the code changes needed to cause it to abort a update early on with a custom message, all that’s left to do is to run grunt build and hit the update button! – Just make sure you’re in /build/ rather than /src/, as it could quickly lead to custom code going missing.. I know this from experience!

Index: src/wp-admin/includes/class-wp-upgrader.php
==================================================================
@@ class Core_Upgrader extends WP_Upgrader
 $working_dir = $this->unpack_package( $download );
 if ( is_wp_error($working_dir) )
 	return $working_dir;

 // Copy update-core.php from the new version into place.
-if ( !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) {
+if ( false && !$wp_filesystem->copy($working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true) ) {
 	$wp_filesystem->delete($working_dir, true);
 	return new WP_Error( 'copy_failed_for_update_core_file', __( 'The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.' ), 'wp-admin/includes/update-core.php' );
 }
 $wp_filesystem->chmod($wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE);

 require_once( ABSPATH . 'wp-admin/includes/update-core.php' );

Index: src/wp-admin/includes/update-core.php
==================================================================
  * @param string $from New release unzipped path.
  * @param string $to   Path to old WordPress installation.
  * @return WP_Error|null WP_Error on failure, null on success.
  */
 function update_core($from, $to) {
 	global $wp_filesystem, $_old_files, $_new_bundled_files, $wpdb;

+	// Demo code to show that this process works
+	echo "Hi! This is text to confirm that I'm using a custom update-core.php file during the update!";
+	die();
+
 	@set_time_limit( 300 );

A few frequently asked questions that have come up in the past with this method:

  1. Question: It’s still downloading the zip file from the internet though!
    Answer: Yes, it does. However my internet connections are usually fast enough that this isn’t a problem.
  2. Question: What if there’s other alterations needed in other update related files?
    Answer: It doesn’t actually matter, update-core.php is the only file from the zip that’s used during update, all the other files (WP_Upgrader / WP_Filesystem / etc) use what’s installed, they’re only overwritten once the update commences using the old code.
  3. Question: How do I stop it from redirecting after the update?
    Answer: When you find out, let me know!  I’ve resorted to simply adding a die(); after the debug code I’m using.
  4. Question: Why isn’t there a grunt task to build the WordPress zips?
    Answer: Haven’t needed one yet I guess? Why don’t you submit a patch on Trac for it? :)

2 thoughts on “Using Grunt to test WordPress Upgrade changes”

Comments are closed.