diff --git a/environments/plugin-directory/.wp-env.test.json b/environments/plugin-directory/.wp-env.test.json index 6bffb7da9c..145db9cad1 100644 --- a/environments/plugin-directory/.wp-env.test.json +++ b/environments/plugin-directory/.wp-env.test.json @@ -4,7 +4,13 @@ "plugins": [ "../wordpress.org/public_html/wp-content/plugins/plugin-directory" ], + "mappings": { + "wp-content/env-bin": "./plugin-directory/bin" + }, "lifecycleScripts": { "afterStart": "bash plugin-directory/bin/after-start-test.sh" + }, + "config": { + "PLUGINS_TABLE_PREFIX": "wp_" } } diff --git a/environments/plugin-directory/bin/after-start-test.sh b/environments/plugin-directory/bin/after-start-test.sh index 13d416d04a..b68d50afcb 100755 --- a/environments/plugin-directory/bin/after-start-test.sh +++ b/environments/plugin-directory/bin/after-start-test.sh @@ -1,7 +1,7 @@ #!/bin/bash # # Runs after wp-env start for the test environment. -# Installs PHPUnit 11 and Yoast polyfills in the test container. +# Installs PHPUnit 11 and Yoast polyfills, and creates the stub tables tests read. # CONFIG="--config plugin-directory/.wp-env.test.json" @@ -10,3 +10,7 @@ RUN="npx wp-env $CONFIG run tests-cli" echo "Installing PHPUnit 11 and polyfills..." $RUN composer global require -W phpunit/phpunit:^11.0 2>&1 $RUN composer require --dev yoast/phpunit-polyfills:^4.0 --working-dir=/wordpress-phpunit 2>&1 + +# Create stub database tables that exist outside WordPress on production. +echo "Creating stub database tables..." +$RUN -- wp db import wp-content/env-bin/database-tables.sql diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 447c8ac037..c4aeb02ab3 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -138,4 +138,14 @@ + + + + + + + + + diff --git a/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/metabox/class-controls.php b/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/metabox/class-controls.php index 3d85569f28..70f8c6ab91 100644 --- a/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/metabox/class-controls.php +++ b/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/metabox/class-controls.php @@ -46,15 +46,22 @@ static function display() { } /** - * Display the release cooldown status and (for reviewers) a force-release control. + * Display the release hold status and (for reviewers) force-release and block controls. * - * Bails when there's no current release to gate, when the release has no cooldown - * delay (feature off at release-creation, or already force-released), or when the - * cooldown window has elapsed. + * Shows one of three messages: a countdown while a release is cooling down, a block notice + * when the release is being held (which outlasts the cooldown window), or a plain notice + * that the version hasn't reached sites yet. Reviewers can force-release in any of them, + * and can block any version that isn't already served. Bails when there's no current + * release, or when the version is being served and isn't held. */ protected static function display_release_cooldown() { $post = get_post(); + // Only plugins the update API serves from have a release to gate. + if ( ! in_array( $post->post_status, array( 'publish', 'disabled', 'closed' ), true ) ) { + return; + } + $version = get_post_meta( $post->ID, 'version', true ); if ( ! $version ) { return; @@ -65,13 +72,21 @@ protected static function display_release_cooldown() { return; } - $release_delay = (int) ( $release['release_delay'] ?? 0 ); - if ( ! $release_delay ) { - return; - } - + $blocked = API_Update_Updater::is_release_blocked( $release ); + $release_delay = (int) ( $release['release_delay'] ?? 0 ); $cooldown_until = API_Update_Updater::compute_release_time( $post, $release ) + $release_delay; - if ( $cooldown_until <= time() ) { + $in_cooldown = $release_delay && $cooldown_until > time(); + + /* + * A version can be held right up until it's written to `update_source`, which lags the + * end of the cooldown by however long the deferred event takes to run. The controls key + * on whether it's actually being served — the same condition block_release() applies — + * so they don't disappear during that window. + */ + $unserved = ( API_Update_Updater::get_served_version( $post->post_name ) !== (string) $version ); + + // Nothing to surface once the version is being served and isn't held. + if ( ! $blocked && ! $unserved ) { return; } @@ -79,21 +94,35 @@ protected static function display_release_cooldown() {

- +