wp-cli / ideas

💡 Ideas and feature requests are collected here
40 stars 1 forks source link

Tool to increment the version number of a plugin #169

Open BrianHenryIE opened 2 years ago

BrianHenryIE commented 2 years ago

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

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.

BrianHenryIE commented 2 years ago

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';
}
schlessera commented 2 years ago

@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.
BrianHenryIE commented 4 months ago

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.

swissspidy commented 4 months ago

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:

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.

ernilambar commented 4 months ago

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