diff --git a/.env.example b/.env.example index 6974d8554611a..ac96332b0ae92 100644 --- a/.env.example +++ b/.env.example @@ -36,6 +36,9 @@ LOCAL_PHP_XDEBUG_MODE=develop,debug # Whether or not to enable Memcached. LOCAL_PHP_MEMCACHED=false +# Whether or not to enable PCOV. +LOCAL_PHP_PCOV=false + ## # The database software to use. # diff --git a/.github/workflows/reusable-phpunit-tests-v3.yml b/.github/workflows/reusable-phpunit-tests-v3.yml index bcad042dfe559..e06f9f24be17e 100644 --- a/.github/workflows/reusable-phpunit-tests-v3.yml +++ b/.github/workflows/reusable-phpunit-tests-v3.yml @@ -84,6 +84,7 @@ env: LOCAL_PHP: ${{ inputs.php }}-fpm LOCAL_PHP_XDEBUG: false LOCAL_PHP_XDEBUG_MODE: 'develop,debug' + LOCAL_PHP_PCOV: ${{ inputs.coverage-report }} LOCAL_DB_TYPE: ${{ inputs.db-type }} LOCAL_DB_VERSION: ${{ inputs.db-version }} LOCAL_PHP_MEMCACHED: ${{ inputs.memcached }} @@ -200,31 +201,6 @@ jobs: - name: Install WordPress run: npm run env:install - # Installs PCOV as the code coverage driver for the PHPUnit run below. - # - # The INI directives tune PCOV for WordPress's codebase: - # - `pcov.enabled` keeps the Zend hooks active (this is the default, but - # stated explicitly for clarity). - # - `pcov.directory` restricts instrumentation to `src/`, so PCOV does not - # record hits for `vendor/`, `tests/`, or WordPress test fixtures that - # PHPUnit would discard at report time anyway. - # - `pcov.initial.files` pre-sizes the internal file tracking array for - # the thousands of files under `src/`, avoiding reallocation churn - # during test warmup. The default of 64 is far too low here. - - name: Install PCOV coverage driver - if: ${{ inputs.coverage-report }} - run: | - docker compose exec -T -u 0 php sh -c ' - pecl install --force pcov-1.0.12 && - docker-php-ext-enable pcov && - { - echo "pcov.enabled=1" - echo "pcov.directory=/var/www/src" - echo "pcov.initial.files=10000" - } >> /usr/local/etc/php/conf.d/docker-php-ext-pcov.ini && - php -m | grep -i pcov - ' - - name: Run PHPUnit tests${{ inputs.phpunit-test-groups && format( ' ({0} groups)', inputs.phpunit-test-groups ) || '' }}${{ inputs.coverage-report && ' with coverage report' || '' }} continue-on-error: ${{ inputs.allow-errors }} run: | diff --git a/docker-compose.yml b/docker-compose.yml index cc2ed8d94975e..0af433a972b13 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,7 @@ services: # The PHP container. ## php: - image: wordpressdevelop/php:${LOCAL_PHP-latest} + image: ghcr.io/wordpress/wpdev-docker-images/php:${LOCAL_PHP-latest}-210 networks: - wpdevnet @@ -40,6 +40,7 @@ services: environment: LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false} XDEBUG_MODE: ${LOCAL_PHP_XDEBUG_MODE-develop,debug} + LOCAL_PHP_PCOV: ${LOCAL_PHP_PCOV-false} LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false} PHP_FPM_UID: ${PHP_FPM_UID-1000} PHP_FPM_GID: ${PHP_FPM_GID-1000} @@ -92,13 +93,14 @@ services: # The WP CLI container. ## cli: - image: wordpressdevelop/cli:${LOCAL_PHP-latest} + image: ghcr.io/wordpress/wpdev-docker-images/cli:${LOCAL_PHP-latest}-210 networks: - wpdevnet environment: LOCAL_PHP_XDEBUG: ${LOCAL_PHP_XDEBUG-false} + LOCAL_PHP_PCOV: ${LOCAL_PHP_PCOV-false} LOCAL_PHP_MEMCACHED: ${LOCAL_PHP_MEMCACHED-false} PHP_FPM_UID: ${PHP_FPM_UID-1000} PHP_FPM_GID: ${PHP_FPM_GID-1000} diff --git a/tools/local-env/php-config.ini b/tools/local-env/php-config.ini index 6f98802e5c68a..30ee177289f1d 100644 --- a/tools/local-env/php-config.ini +++ b/tools/local-env/php-config.ini @@ -5,3 +5,9 @@ post_max_size = 1G xdebug.start_with_request=trigger xdebug.discover_client_host=true xdebug.client_host=host.docker.internal + +# Pre-sizes the internal file tracking array for the thousands of files under +# `src/` or `build/`, avoiding reallocation churn during test warmup. +# +# The default of 64 is far too low here. +pcov.initial.files=10000 diff --git a/tools/local-env/scripts/docker.js b/tools/local-env/scripts/docker.js index c7b11f0058424..8391d2f5c6e98 100644 --- a/tools/local-env/scripts/docker.js +++ b/tools/local-env/scripts/docker.js @@ -20,6 +20,25 @@ if ( [ 'exec', 'run' ].includes( dockerCommand[0] ) && ! process.stdin.isTTY ) { dockerCommand.splice( 1, 0, '--no-TTY' ); } +/* + * `pcov.directory` restricts instrumentation to the configured `LOCAL_DIR`. This prevents PCOV from recording hits for + * `vendor/`, `tests/`, or WordPress test fixtures that PHPUnit would discard at report time anyway. + */ +if ( process.env.LOCAL_PHP_PCOV === 'true' && dockerCommand.includes( '--coverage-clover' ) ) { + const phpunitIdx = dockerCommand.findIndex( ( arg ) => typeof arg === 'string' && arg.endsWith( 'phpunit' ) ); + if ( phpunitIdx !== -1 ) { + const localDir = process.env.LOCAL_DIR || 'src'; + dockerCommand.splice( + phpunitIdx, + 1, + 'php', + '-d', + `pcov.directory=/var/www/${ localDir }`, + dockerCommand[ phpunitIdx ] + ); + } +} + // Add a --defaults flag to any db command WP-CLI command. See https://core.trac.wordpress.org/ticket/63876. if ( dockerCommand.includes( 'cli' ) && dockerCommand.includes( 'db' ) && ! dockerCommand.includes( '--defaults' ) ) { dockerCommand.push( '--defaults' );