diff --git a/.github/workflows/phpunit-tests.yml b/.github/workflows/phpunit-tests.yml index 420506d42265c..cafb62f4f26c4 100644 --- a/.github/workflows/phpunit-tests.yml +++ b/.github/workflows/phpunit-tests.yml @@ -61,7 +61,7 @@ jobs: # test-with-mysql: name: PHP ${{ matrix.php }} - uses: ./.github/workflows/reusable-phpunit-tests-v3.yml + uses: ./.github/workflows/reusable-phpunit-tests-v4.yml permissions: contents: read secrets: inherit @@ -138,7 +138,7 @@ jobs: # test-with-mariadb: name: PHP ${{ matrix.php }} - uses: ./.github/workflows/reusable-phpunit-tests-v3.yml + uses: ./.github/workflows/reusable-phpunit-tests-v4.yml permissions: contents: read secrets: inherit @@ -190,7 +190,7 @@ jobs: # test-innovation-releases: name: PHP ${{ matrix.php }} - uses: ./.github/workflows/reusable-phpunit-tests-v3.yml + uses: ./.github/workflows/reusable-phpunit-tests-v4.yml permissions: contents: read secrets: inherit @@ -233,7 +233,7 @@ jobs: # html-api-test-groups: name: ${{ matrix.label }} - uses: ./.github/workflows/reusable-phpunit-tests-v3.yml + uses: ./.github/workflows/reusable-phpunit-tests-v4.yml permissions: contents: read secrets: inherit @@ -262,7 +262,7 @@ jobs: # limited-matrix-for-forks: name: PHP ${{ matrix.php }} - uses: ./.github/workflows/reusable-phpunit-tests-v3.yml + uses: ./.github/workflows/reusable-phpunit-tests-v4.yml permissions: contents: read secrets: inherit diff --git a/.github/workflows/reusable-phpunit-tests-v4.yml b/.github/workflows/reusable-phpunit-tests-v4.yml new file mode 100644 index 0000000000000..59f1ae213a297 --- /dev/null +++ b/.github/workflows/reusable-phpunit-tests-v4.yml @@ -0,0 +1,277 @@ +## +# A reusable workflow that runs the PHPUnit test suite with the specified configuration. +# +# This workflow is used by `trunk` and branches >= 6.9. +## +name: Run PHPUnit tests + +on: + workflow_call: + inputs: + os: + description: 'Operating system to run tests on' + required: false + type: 'string' + default: 'ubuntu-24.04' + php: + description: 'The version of PHP to use, in the format of X.Y' + required: true + type: 'string' + db-type: + description: 'Database type. Valid types are mysql and mariadb' + required: false + type: 'string' + default: 'mysql' + db-version: + description: 'Database version' + required: false + type: 'string' + default: '8.4' + db-innovation: + description: 'Whether a database software innovation release is being tested.' + required: false + type: 'boolean' + default: false + multisite: + description: 'Whether to run tests as multisite' + required: false + type: 'boolean' + default: false + memcached: + description: 'Whether to test with memcached enabled' + required: false + type: 'boolean' + default: false + phpunit-config: + description: 'The PHPUnit configuration file to use' + required: false + type: 'string' + default: 'phpunit.xml.dist' + phpunit-test-groups: + description: 'A list of test groups to run.' + required: false + type: 'string' + default: 'media' + tests-domain: + description: 'The domain to use for the tests' + required: false + type: 'string' + default: 'example.org' + coverage-report: + description: 'Whether to generate a code coverage report.' + required: false + type: boolean + default: false + report: + description: 'Whether to report results to WordPress.org Hosting Tests' + required: false + type: 'boolean' + default: false + allow-errors: + description: 'Whether to continue when test errors occur.' + required: false + type: boolean + default: false + install-imagemagick: + description: 'Whether to install ImageMagick.' + required: false + type: boolean + default: true + secrets: + CODECOV_TOKEN: + description: 'The Codecov token required for uploading reports.' + required: false + WPT_REPORT_API_KEY: + description: 'The WordPress.org Hosting Tests API key.' + required: false + +env: + LOCAL_PHP_MEMCACHED: ${{ inputs.memcached }} + PHPUNIT_CONFIG: ${{ inputs.phpunit-config }} + PUPPETEER_SKIP_DOWNLOAD: ${{ true }} + +jobs: + # Runs the PHPUnit tests for WordPress. + # + # Performs the following steps: + # - Sets environment variables. + # - Checks out the repository. + # - Sets up Node.js. + # - Sets up PHP. + # - Installs Composer dependencies. + # - Installs npm dependencies + # - Logs general debug information about the runner. + # - Logs Docker debug information (about the Docker installation within the runner). + # - Starts the WordPress Docker container. + # - Logs the running Docker containers. + # - Logs debug information about what's installed within the WordPress Docker containers. + # - Install WordPress within the Docker container. + # - Run the PHPUnit tests. + # - Upload the code coverage report to Codecov.io. + # - Upload the HTML code coverage report as an artifact. + # - Ensures version-controlled files are not modified or deleted. + # - Checks out the WordPress Test reporter repository. + # - Submit the test results to the WordPress.org host test results. + phpunit-tests: + name: ${{ ( inputs.phpunit-test-groups || inputs.coverage-report ) && format( 'PHP {0} with ', inputs.php ) || '' }} ${{ 'mariadb' == inputs.db-type && 'MariaDB' || 'MySQL' }} ${{ inputs.db-version }}${{ inputs.multisite && ' multisite' || '' }}${{ inputs.db-innovation && ' (innovation release)' || '' }}${{ inputs.memcached && ' with memcached' || '' }}${{ inputs.report && ' (test reporting enabled)' || '' }} ${{ 'example.org' != inputs.tests-domain && inputs.tests-domain || '' }} + runs-on: ${{ inputs.os }} + timeout-minutes: ${{ inputs.coverage-report && 120 || inputs.php == '8.4' && 30 || 20 }} + permissions: + contents: read + + services: + database: + image: ${{ inputs.db-type }}:${{ inputs.db-version }} + ports: + - 3306 + env: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: wordpress_develop_tests + options: >- + --health-cmd="${{ inputs.db-type == 'mariadb' && ! contains( fromJSON( '["5.5", "10.0", "10.1", "10.2", "10.3"]' ), inputs.db-version ) && 'mariadb-admin ping' || 'mysqladmin ping' }}" + --health-interval="30s" + --health-timeout="10s" + --health-retries="5" + ${{ inputs.db-type == 'mysql' && contains( fromJSON('["7.2", "7.3"]'), inputs.php ) && inputs.db-version == '8.4' && '--authentication-policy=mysql_native_password' || '' }} + ${{ inputs.db-type == 'mysql' && contains( fromJSON('["7.2", "7.3"]'), inputs.php ) && inputs.db-version != '8.4' && '--default-authentication-plugin=mysql_native_password' || '' }} + + steps: + - name: Install ImageMagick with AVIF support + if: ${{ inputs.install-imagemagick }} + run: | + sudo apt-get remove --purge -y imagemagick imagemagick-6-common libmagickcore-6* libmagickwand-6* + sudo apt-get autoremove -y + which magick || echo "ImageMagick removed" + sudo apt-get update + sudo apt-get install -y \ + build-essential pkg-config autoconf automake libtool \ + libjpeg-dev libpng-dev libtiff-dev zlib1g-dev \ + libheif-dev libaom-dev libdav1d-dev libde265-dev + curl -fsSL https://imagemagick.org/archive/ImageMagick.tar.gz | tar xz + cd ImageMagick-* + ./configure --with-heic=yes + make -j"$(nproc)" + sudo make install + sudo ldconfig + + - name: Confirm AVIF support + run: magick -version | grep Delegates + + - name: Confirm image format support + run: magick -list format + + - name: Log PHP debugging information + run: php -i + + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Set up PHP + uses: shivammathur/setup-php@20529878ed81ef8e78ddf08b480401e6101a850f # v2.35.3 + with: + php-version: '${{ inputs.php }}' + coverage: ${{ inputs.coverage-report && 'xdebug' || 'none' }} + tools: wp-cli + + # Since Composer dependencies are installed using `composer update` and no lock file is in version control, + # passing a custom cache suffix ensures that the cache is flushed at least once per week. + - name: Install Composer dependencies + uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1 + with: + custom-cache-suffix: $(/bin/date -u --date='last Mon' "+%F") + + - name: Install npm dependencies + run: npm ci + + - name: General debug information + run: | + npm --version + node --version + curl --version + git --version + composer --version + locale -a + + - name: Create wp-tests-config.php file + run: cp wp-tests-config-sample.php wp-tests-config.php + + - name: Change DB_NAME value + run: wp config set DB_NAME wordpress_develop_tests --config-file=wp-tests-config.php + + - name: Change DB_USER value + run: wp config set DB_USER root --config-file=wp-tests-config.php + + - name: Change DB_PASSWORD value + run: wp config set DB_PASSWORD password --config-file=wp-tests-config.php + + - name: Change DB_HOST value + run: wp config set DB_HOST 127.0.0.1:${{ job.services.database.ports['3306'] }} --config-file=wp-tests-config.php + + - 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: ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }}${{ inputs.phpunit-test-groups && format( ' --group {0}', inputs.phpunit-test-groups ) || '' }}${{ inputs.coverage-report && format( ' --coverage-clover wp-code-coverage-{0}-{1}.xml --coverage-html wp-code-coverage-{0}-{1}', ( inputs.multisite && 'multisite' || 'single' ), github.sha ) || '' }} + + - name: Run AJAX tests + if: ${{ ! inputs.phpunit-test-groups && ! inputs.coverage-report }} + continue-on-error: ${{ inputs.allow-errors }} + run: ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} --group ajax + + - name: Run ms-files tests as a multisite install + if: ${{ inputs.multisite && ! inputs.phpunit-test-groups && ! inputs.coverage-report }} + continue-on-error: ${{ inputs.allow-errors }} + run: ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} --group ms-files + + - name: Run external HTTP tests + if: ${{ ! inputs.multisite && ! inputs.phpunit-test-groups && ! inputs.coverage-report }} + continue-on-error: ${{ inputs.allow-errors }} + run: ./vendor/bin/phpunit --verbose -c ${{ env.PHPUNIT_CONFIG }} --group external-http + + # __fakegroup__ is excluded to force PHPUnit to ignore the settings in phpunit.xml.dist. + - name: Run (Xdebug) tests + if: ${{ inputs.php != '8.4' && ! inputs.phpunit-test-groups && ! inputs.coverage-report }} + continue-on-error: ${{ inputs.allow-errors }} + run: LOCAL_PHP_XDEBUG=true node ./tools/local-env/scripts/docker.js run php ./vendor/bin/phpunit -v --group xdebug --exclude-group __fakegroup__ + + - name: Upload test coverage report to Codecov + if: ${{ inputs.coverage-report }} + uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: wp-code-coverage${{ inputs.multisite && '-multisite' || '-single' }}-${{ github.sha }}.xml + flags: ${{ inputs.multisite && 'multisite' || 'single' }},php + fail_ci_if_error: true + + - name: Upload HTML coverage report as artifact + if: ${{ inputs.coverage-report }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: wp-code-coverage${{ inputs.multisite && '-multisite' || '-single' }}-${{ github.sha }} + path: wp-code-coverage${{ inputs.multisite && '-multisite' || '-single' }}-${{ github.sha }} + overwrite: true + + - name: Ensure version-controlled files are not modified or deleted + run: git diff --exit-code + + - name: Checkout the WordPress Test Reporter + if: ${{ github.ref == 'refs/heads/trunk' && inputs.report }} + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: 'WordPress/phpunit-test-runner' + path: 'test-runner' + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + persist-credentials: false + + - name: Submit test results to the WordPress.org host test results + if: ${{ github.ref == 'refs/heads/trunk' && inputs.report }} + env: + WPT_REPORT_API_KEY: "${{ secrets.WPT_REPORT_API_KEY }}" + run: docker compose run --rm -e WPT_REPORT_API_KEY -e WPT_PREPARE_DIR=/var/www -e WPT_TEST_DIR=/var/www php php test-runner/report.php