wp-cli / extension-command

Manages plugins and themes, including installs, activations, and updates.
MIT License
90 stars 79 forks source link

Cache `wp plugin install` from GitHub #363

Open Luc45 opened 1 year ago

Luc45 commented 1 year ago

Feature Request

Describe your use case and the problem you are facing

Downloads from wp plugin install <GitHub URL> are not cached.

Describe the solution you'd like

I'd like these downloads to be cached, or maybe optionally cached.

Eg: wp plugin install https://github.com/woocommerce/woocommerce/releases/download/7.6.1/woocommerce.zip

I don't know if this is the best possible solution, but I'm currently using this mu-plugin in my site to cache GitHub downloads:

<?php
/*
 * Plugin name: WP CLI GitHub Cache
 */

if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
    return;
}

/*
 * Cache downloads of "wp plugin install" from GitHub repos.
 */
WP_CLI::add_hook( 'before_run_command', static function ( $args, $assoc_args, $options ) {
    // Early bail: Unexpected value;
    if ( ! is_array( $args ) || count( $args ) < 3 ) {
        return;
    }

    // We want only "plugin install"
    if ( $args[0] !== 'plugin' || $args[1] !== 'install' ) {
        return;
    }

    // We want only plugin installs of GitHub repos.
    if ( stripos( $args[2], 'github.com' ) === false ) {
        return;
    }

    // Invalid URL.
    if ( ! filter_var( $args[2], FILTER_VALIDATE_URL ) ) {
        return;
    }

    $parts = explode( '/', $args[2] );

    $last_part = end( $parts );

    if ( ! str_ends_with( $last_part, '.zip' ) ) {
        return;
    }

    WP_CLI::get_http_cache_manager()->whitelist_package( $args[2], 'plugin', basename( $last_part, '.zip' ), 'github', 86400 );
} );

Result:

wp plugin install https://github.com/woocommerce/woocommerce/releases/download/7.6.1/woocommerce.zip --force
Downloading installation package from https://github.com/woocommerce/woocommerce/releases/download/7.6.1/woocommerce.zip...
Using cached file '/var/cd-cache/.wp-cli/cache/plugin/woocommerce-github.zip'...
Unpacking the package...
Installing the plugin...
Removing the old version of the plugin...
Plugin updated successfully.
Success: Installed 1 of 1 plugins

The problem here seems to be how to invalidate cache if the remote URL changed. The approach that I'm taking is caching for 1 day, which is a short period compared to the default 6 months of TTL.

danielbachhuber commented 1 year ago

Thanks for the suggestion, @Luc45 !

I'm open to a PR for this. We should make sure to include the full URL in the cache key, though.