ideas icon indicating copy to clipboard operation
ideas copied to clipboard

Tool to increment the version number of a plugin

Open BrianHenryIE opened this issue 3 years ago • 5 comments

When developing plugins and releasing new versions, I need to increment the version in three locations:

  • the plugin file header
  • defined as a const in the plugin file PHP body
  • in a getter in my settings.php.

I'm thinking ~ wp increment-plugin-version plugin.php /list/of/paths/to/other/files.php --major where it pulls the current version from plugin.php, increments the major/minor/patch version as requested, and does a find and replace for the past version -> new version in the files listed, and prints out the changes.

I see a comment by @schlessera referencing WP_CLI\Utils\get_file_header(), but that doesn't seem to exist. I see the function seems to be I18n's FileDataExtractor.

  • Is there an existing command this should be a sub-command to?
  • Was get_file_header() ever in WP_CLI\Utils, i.e. was it moved out for any reason/is there any reason it cannot be moved there?
  • Any other suggestions on the name or parameters?

BrianHenryIE avatar Oct 21 '22 23:10 BrianHenryIE

Here's the gist, outside of WP CLI:

<?php

$positional_args = array();
$named_args      = array();

// The path of this PHP file is $argv[0].
unset( $argv[0] );
foreach ( $argv as $arg ) {
	if ( 0 === strpos( $arg, '--' ) ) {
		$split                   = explode( '=', substr( $arg, 2 ) );
		$named_args[ $split[0] ] = $split[1];
	} else {
		$positional_args[] = $arg;
	}
}

$version_to_increment = isset( $named_args['version'] ) ? $named_args['version'] : 'patch';

$plugin_file = isset( $positional_args[0] ) ? $positional_args[0] : basename( getcwd() ) . '.php';

$plugin_file_path = getcwd() . '/' . $plugin_file;

$file_contents = file_get_contents( $plugin_file_path );

if ( false !== preg_match_all( '/(\s*\*\s*Version:\s*)(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/', $file_contents, $matches ) ) {

	$version_major = $matches['major'][0];
	$version_minor = $matches['minor'][0];
	$version_patch = $matches['patch'][0];

	$old_version = "$version_major.$version_minor.$version_patch";

	switch ( $version_to_increment ) {
		case 'major':
			++$version_major;
			$version_minor = 0;
			$version_patch = 0;
			break;
		case 'minor':
			++$version_minor;
			$version_patch = 0;
			break;
		default:
			++$version_patch;
	}

	$new_version = "$version_major.$version_minor.$version_patch";

	error_log( "Incrementing version from $old_version to $new_version." );

	$file_content_updated_header = str_replace( $matches[0][0], $matches[1][0] . $new_version, $file_contents );

	$file_content_updated_throughout = preg_replace( '/(["\'])' . $old_version . '(["\'])/', "'$new_version'", $file_content_updated_header );

	file_put_contents( $plugin_file_path, $file_content_updated_throughout );

	error_log( "Version incremented in $plugin_file_path" );

	foreach ( $positional_args as $file_path ) {
		if ( 0 !== strpos( $file_path, '/' ) ) {
			$file_path = getcwd() . '/' . $file_path;
		}
		if ( $file_path === $plugin_file_path ) {
			continue;
		}
		if ( ! file_exists( $file_path ) ) {
			error_log( 'File not found: ' . $file_path );
			continue;
		}
		$file_contents         = file_get_contents( $file_path );
		$file_contents_updated = preg_replace( '/(["\'])' . $old_version . '(["\'])/', "'$new_version'", $file_contents );
		if ( $file_contents_updated !== $file_contents ) {
			file_put_contents( $file_path, $file_contents_updated );
			error_log( "Version incremented in $file_path" );
		} else {
			error_log( "Failed to find old version $old_version in $file_path" );
		}
	}
} else {
	echo 'Failed to get plugin version from file';
}

BrianHenryIE avatar Oct 22 '22 00:10 BrianHenryIE

@BrianHenryIE First of all, I'm not sure it makes sense to have this be a WP-CLI command, as there's no benefit to be had from executing WordPress or using WordPress-specific contextual knowledge to make this work. It is basically just a smart sed command.

That being said, I still want to answer your questions above:

  1. In case we'd agree that this should be a WP-CLI command, then the most fitting would be the plugin command, using something like wp plugin increment-version.
  2. No, this has never existed so far, and the comment you're referring to suggested that we should copy the WP version of this into a WP-CLI\Utils\get_file_header() version to internalize it and decouple it from a WP installation. This has not happened yet, but would be the suggested way to go about this.
  3. As shown as an example in 1., this should follow the wp <noun> <verb> structure, like wp plugin increment-version.

schlessera avatar Oct 24 '22 13:10 schlessera

Tagging #193 as related.

And while I'm here, to note wppm.io as a SaaS that addresses this problem.

I agree WordPress does not need to be loaded, and that it is just a fancy sed, but it is a problem whose solution has been reinvented by hundreds if not thousands of developers. I don't want to close this yet, I'll leave it open with the hope I can perfectly, succinctly address it eventually.

I'm imagining a step in a GitHub Actions release workflow ~ if version != tag, wp plugin increment-version $tag.

BrianHenryIE avatar Jul 12 '24 03:07 BrianHenryIE

I'm definitely guilty of reinventing such a fancy sed myself. Like in the original issue description, in my projects I usually need to bump the version in multiple places:

  • Main plugin file header (
  • A constant in the main plugin file (sometimes contains a git hash)
  • readme.txt Stable Tag (if doing a stable release and not a nightly)

In other projects there are also some more complex scripts where the version number is just a placeholder (even in @since docblocks) and then before the release it is updated with the new version number.

So far these projects have all had their differences, so I am not sure if there is a one-size-fits-all solution for this kind of task. And if so, it might not necessarily be WP-CLI.

swissspidy avatar Jul 12 '24 07:07 swissspidy

I also needed similar tool so that I dont miss updating plugin version. So I created node package for the purpose. https://github.com/ernilambar/easy-replace-in-files

ernilambar avatar Jul 12 '24 11:07 ernilambar