Making WordPress.org

Changeset 14565


Ignore:
Timestamp:
10/24/2025 06:11:26 AM (12 months ago)
Author:
dd32
Message:

Plugin Directory: Run Plugin Check over new plugin releases.

Props davidperez, dd32.
Closes ​https://github.com/WordPress/wordpress.org/pull/515
See #6108, #5637, #5868.
Fixes #8018.

Location:
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/jobs/class-manager.php

    r14412 r14565  
    2222                'import_plugin_i18n' => array( __NAMESPACE__ . '\Plugin_i18n_Import', 'cron_trigger' ),
    2323                'import_zip'         => array( __NAMESPACE__ . '\Plugin_ZIP_Import', 'cron_trigger' ),
     24                'scan_plugin'        => array( __NAMESPACE__ . '\Plugin_Updates_PCP', 'cron_trigger' ),
    2425        );
    2526
    … …  
    4142                add_action( 'plugin_directory_daily_post_checks', array( __NAMESPACE__ . '\Daily_Post_Checks', 'cron_trigger' ) );
    4243                add_action( 'plugin_directory_create_svn_repo', array( __NAMESPACE__ . '\SVN_Repo_Creation', 'cron_trigger' ) );
     44
     45                // Hook into the plugin import process to queue a job.
     46                add_action( 'wporg_plugins_imported', array( __NAMESPACE__ . '\Plugin_Updates_PCP', 'wporg_plugins_imported' ), 10, 5 );
    4347
    4448                // A cronjob to check cronjobs
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php

    r14494 r14565  
    44use WP_Error;
    55use WordPressdotorg\Plugin_Directory\CLI\Import;
     6use WordPressdotorg\Plugin_Directory\Jobs\Plugin_Updates_PCP;
    67use WordPressdotorg\Plugin_Directory\Readme\Parser;
    78use WordPressdotorg\Plugin_Directory\Plugin_Directory;
    … …  
    656657
    657658        /**
    658          * Sends a plugin through Plugin Check.
     659         * Checks the uploaded plugin via Plugin Check.
    659660         *
    660661         * @return array The results of the plugin check.
    661662         */
    662663        public function check_plugin() {
    663                 // Run the checks.
    664                 if (
    665                         ! defined( 'WPCLI' ) ||
    666                         ! defined( 'WP_CLI_CONFIG_PATH' ) ||
    667                         // The plugin must be activated in order to have plugin-check run.
    668                         ! defined( 'WP_PLUGIN_CHECK_VERSION' ) ||
    669                         // WordPress.org only..
    670                         ! function_exists( 'notify_slack' )
    671                 ) {
    672                         // If we can't run plugin-check, we'll just return a pass.
    673                         return [
    674                                 'verdict' => true,
    675                                 'results' => [],
    676                                 'html'    => '',
    677                         ];
    678                 }
    679 
    680                 // Run plugin check via CLI
    681                 $start_time = microtime(1);
    682                 $env_vars   = [
    683                         'PATH'               => $_ENV['PATH'] ?? '/usr/local/bin:/usr/bin:/bin',
    684                         'WP_CLI_CONFIG_PATH' => WP_CLI_CONFIG_PATH,
     664                // If we can't run plugin-check, we'll just return a pass.
     665                $default_return = [
     666                        'verdict' => true,
     667                        'results' => [],
     668                        'html'    => '',
    685669                ];
    686                 $command    = WPCLI . ' --url=https://wordpress.org/plugins ' .
    687                               'plugin check ' .
    688                               '--error-severity=7 --warning-severity=6 --include-low-severity-errors ' .
    689                               '--categories=plugin_repo --format=json ' .
    690                               '--slug=' . escapeshellarg( $this->plugin_slug ) . ' ' .
    691                               escapeshellarg( $this->plugin_root );
    692 
    693                 $plugin_check_process = proc_open(
    694                         $command,
    695                         [
    696                                 1 => [ 'pipe', 'w' ], // STDOUT
    697                                 2 => [ 'pipe', 'w' ], // STDERR
    698                         ],
    699                         $pipes,
    700                         null,
    701                         $env_vars
    702                 );
    703                 if ( ! $plugin_check_process ) {
    704                         // If we can't run plugin-check, we'll just return a pass.
    705                         return [
    706                                 'verdict' => true,
    707                                 'results' => [],
    708                                 'html'    => '',
    709                         ];
    710                 }
    711                 do {
    712                         usleep( 100000 ); // 0.1s
    713 
    714                         $total_time = round( microtime(1) - $start_time, 1 );
    715 
    716                         $proc_status = proc_get_status( $plugin_check_process );
    717                         $return_code = $proc_status['exitcode'] ?? 1;
    718 
    719                         if ( $total_time >= 45 && $proc_status['running'] ) {
    720                                 // Terminate it.
    721                                 proc_terminate( $plugin_check_process );
    722                         }
    723                 } while ( $proc_status['running'] && $total_time <= 60 ); // 60s max, just in case.
    724 
    725                 $output = stream_get_contents( $pipes[1] );
    726                 $stderr = rtrim( stream_get_contents( $pipes[2] ), "\n" );
    727 
    728                 // Remove ABSPATH from the output if present.
    729                 $output = str_replace( ABSPATH, '/', $output );
    730                 $output = str_replace( str_replace( '/', '\/', ABSPATH ), '\/', $output ); // JSON encoded
    731                 $stderr = str_replace( ABSPATH, '/', $stderr );
    732 
    733                 // Close the process.
    734                 fclose( $pipes[1] );
    735                 fclose( $pipes[2] );
    736                 proc_close( $plugin_check_process );
    737 
    738                 /**
    739                  * Anything that plugin-check outputs that we want to discard completely.
    740                  */
    741                 $is_ignored_code = static function( $code ) {
    742                         $ignored_codes = [
    743                         ];
    744 
    745                         return (
    746                                 in_array( $code, $ignored_codes, true ) ||
    747                                 // All the Readme parser warnings are duplicated, we'll exclude those.
    748                                 str_starts_with( $code, 'readme_parser_warnings_' )
    749                         );
    750                 };
    751 
    752                 /*
    753                  * Convert the output into an array.
    754                  * Format:
    755                  * FILE: example.extension
    756                  * [{.....}]
    757                  *
    758                  * FILE: example2.extension
    759                  * [{.....}]
    760                  */
    761                 $verdict         = true;
    762                 $results         = [];
    763                 $results_by_type = [];
    764                 $output          = explode( "\n", $output );
    765                 foreach ( array_chunk( $output, 3 ) as $file_result ) {
    766                         if ( ! str_starts_with( $file_result[0], 'FILE:' ) ) {
    767                                 continue;
    768                         }
    769 
    770                         $filename = trim( explode( ':' , $file_result[0], 2 )[1] );
    771                         $json     = json_decode( $file_result[1], true );
    772 
    773                         foreach ( $json as $record ) {
    774                                 $record['file'] = $filename;
    775 
    776                                 if ( $is_ignored_code( $record['code'] ) ) {
    777                                         continue;
    778                                 }
    779 
    780                                 $results[] = $record;
    781 
    782                                 $results_by_type[ $record['type'] ] ??= [];
    783                                 $results_by_type[ $record['type'] ][] = $record;
    784 
    785                                 // Record submission stats.
    786                                 if ( function_exists( 'bump_stats_extra' ) && 'production' === wp_get_environment_type() ) {
    787                                         bump_stats_extra( 'plugin-check-' . $record['type'], $record['code'] );
    788                                 }
    789 
    790                                 // Determine if it failed the checks.
    791                                 if ( $verdict && 'ERROR' === $record['type'] ) {
    792                                         $verdict = false;
    793                                 }
    794                         }
    795                 }
     670
     671                if ( ! function_exists( 'notify_slack' ) ) {
     672                        return $default_return;
     673                }
     674
     675                $result = Plugin_Updates_PCP::run_plugin_check( $this->plugin_slug, $this->plugin_root, '' /* should be stable tag */, 'new' );
     676                if ( false === $result ) {
     677                        return $default_return;
     678                }
     679
     680                $verdict     = $result['verdict'];
     681                $results     = $result['results'];
     682                $return_code = $result['return_code'];
     683                $total_time  = $result['total_time'];
    796684
    797685                // Generage the HTML for the Plugin Check output.
    … …  
    838726                if ( ! $verdict ) {
    839727                        // Slack dm the logs.
    840                         $zip_name = reset( $_FILES )['name'];
     728                        $zip_name = reset( $_FILES )['name'] ?? '';
    841729                        $failpass = $verdict ? ':white_check_mark: passed' : ':x: failed';
    842730                        if ( $return_code > 1 ) { // TODO: Temporary, as we're always hitting this branch.
    … …  
    879767                } elseif ( $return_code ) {
    880768                        // Log plugin-check timing out.
    881                         $zip_name   = reset( $_FILES )['name'];
     769                        $zip_name   = reset( $_FILES )['name'] ?? '';
    882770                        $output     = implode( "\n", $output );
    883771                        $debug      = '';
Note: See TracChangeset for help on using the changeset viewer.