Likes: add minified build for CSS #106238
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Tests | |
| on: | |
| pull_request: | |
| push: | |
| branches: ['trunk', '*/branch-*'] | |
| concurrency: | |
| # Trunk runs need to not be cancelled for concurrency, mainly for code coverage. Everything else can be. | |
| group: tests-${{ github.event_name }}-${{ github.ref }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/trunk' && github.run_id || '' }} | |
| cancel-in-progress: true | |
| permissions: | |
| # actions/checkout, actions/upload-artifact, actions/download-artifact | |
| contents: read | |
| # Note posting the coverage comment uses an app token, so no need for permissions | |
| env: | |
| COMPOSER_ROOT_VERSION: 'dev-trunk' | |
| jobs: | |
| create-matrix: | |
| name: 'Determine tests matrix' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 2 # 2025-11-20: Takes a few seconds. | |
| outputs: | |
| matrix: ${{ steps.create-matrix.outputs.matrix }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - id: create-matrix | |
| run: | | |
| MATRIX="$(.github/files/generate-ci-matrix.php)" | |
| echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" | |
| run-tests: | |
| name: ${{ matrix.name }} | |
| runs-on: ${{ matrix.runner }} | |
| needs: create-matrix | |
| services: | |
| database: | |
| image: mariadb:12.0 | |
| env: | |
| MARIADB_ROOT_PASSWORD: root | |
| ports: | |
| - 3306:3306 | |
| options: --health-cmd="healthcheck.sh --su-mysql --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=5 | |
| continue-on-error: ${{ matrix.experimental }} | |
| timeout-minutes: ${{ matrix.timeout }} | |
| env: | |
| TEST_SCRIPT: ${{ matrix.script }} | |
| WP_BRANCH: ${{ matrix.wp }} | |
| PHP_VERSION: ${{ matrix.php }} | |
| NODE_VERSION: ${{ matrix.node }} | |
| MONOREPO_BASE: ${{ github.workspace }} | |
| WITH_WOOCOMMERCE: ${{ matrix.with-woocommerce }} | |
| WITH_WPCOMSH: ${{ matrix.with-wpcomsh }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJson( needs.create-matrix.outputs.matrix ) }} | |
| # Note matrix-job outputs are kind of weird. Last-to-run job that sets a non-empty value wins. | |
| outputs: | |
| did-coverage: ${{ ( steps.run-tests.conclusion != 'cancelled' && steps.process-coverage.conclusion == 'success' && steps.upload-artifacts.conclusion == 'success' ) && 'true' || '' }} | |
| coverage-status: ${{ matrix.script == 'test-coverage' && steps.run-tests.conclusion || '' }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| # Test coverage checks require a fetch depth > 1. | |
| fetch-depth: 2 | |
| # For pull requests, list-changed-projects.sh needs the merge base. | |
| # But it doesn't have to be checked out. | |
| - name: Deepen to merge base | |
| if: github.event_name == 'pull_request' | |
| uses: ./.github/actions/deepen-to-merge-base | |
| with: | |
| checkout: false | |
| - name: Setup tools | |
| uses: ./.github/actions/tool-setup | |
| with: | |
| php: ${{ matrix.php }} | |
| coverage: ${{ matrix.script == 'test-coverage' && 'pcov' || 'none' }} | |
| node: ${{ matrix.node }} | |
| - name: Monorepo install | |
| run: | | |
| echo "::group::Pnpm" | |
| pnpm install | |
| echo "::endgroup::" | |
| - name: Detect changed projects | |
| id: changed | |
| run: | | |
| CHANGED="$(EXTRA=test .github/files/list-changed-projects.sh)" | |
| # Only test certain plugins in combination with WC | |
| if [[ "$WITH_WOOCOMMERCE" == true ]]; then | |
| echo "Testing with WooCommerce, filtering for projects that have WooCommerce-specific tests." | |
| CHANGED=$( jq -c 'with_entries( select( .key == "plugins/jetpack" ) )' <<<"$CHANGED" ) | |
| fi | |
| # Ensure certain plugins are tested if WITH_WPCOMSH and wpcomsh is changed. | |
| if [[ "$WITH_WPCOMSH" == true ]] && jq -e '.["plugins/wpcomsh"] // false' <<<"$CHANGED" > /dev/null; then | |
| echo "Testing with wpcomsh, making sure projects that have wpcomsh-specific tests are also tested." | |
| CHANGED=$( jq -c '. += { "plugins/jetpack": true }' <<<"$CHANGED" ) | |
| fi | |
| ANY_PLUGINS="$(jq --argjson changed "$CHANGED" -n '$changed | with_entries( select( .key | startswith( "plugins/" ) ) ) | any')" | |
| echo "projects=${CHANGED}" >> "$GITHUB_OUTPUT" | |
| echo "any-plugins=${ANY_PLUGINS}" >> "$GITHUB_OUTPUT" | |
| - name: Select WordPress version | |
| if: matrix.wp != 'none' | |
| run: .github/files/select-wordpress-tag.sh | |
| - name: Composer Install | |
| env: | |
| CHANGED: ${{ steps.changed.outputs.projects }} | |
| run: | | |
| # If we're going to be making WorDBless use WP "nightlies", remove the relevant package from Composer's cache to get the latest version. | |
| if [[ "$WP_BRANCH" == 'trunk' && ( "$TEST_SCRIPT" == "test-php" || "$TEST_SCRIPT" == "test-coverage" ) ]]; then | |
| echo "::group::Clear composer cache for roots/wordpress" | |
| DIR=$(composer config cache-files-dir) | |
| rm -rf "$DIR/roots/wordpress" "$DIR/roots/wordpress-no-content" | |
| echo "::endgroup::" | |
| fi | |
| echo "::group::Composer" | |
| composer install --working-dir=tools/php-test-env | |
| if [[ ( "$TEST_SCRIPT" == "test-php" || "$TEST_SCRIPT" == "test-coverage" ) && ( "$WP_BRANCH" == 'trunk' || "$WP_BRANCH" == 'previous' ) ]]; then | |
| VER=$(composer --format=json --working-dir="tools/php-test-env" show | jq -r '.installed[] | select( .name == "roots/wordpress" ) | .version') | |
| if [[ -n "$VER" ]]; then | |
| INSVER=$WORDPRESS_TAG | |
| [[ "$WORDPRESS_TAG" == 'trunk' ]] && INSVER="dev-main as $VER" | |
| echo "Supposed to run tests against WordPress $WORDPRESS_TAG, so setting roots/wordpress and roots/wordpress-no-content to \"$INSVER\"" | |
| # Composer seems to sometimes have issues with deleting the wordpress dir on its own, so do it manually first. | |
| rm -rf "tools/php-test-env/wordpress" | |
| composer --working-dir="tools/php-test-env" require --dev "roots/wordpress:$INSVER" "roots/wordpress-no-content:$INSVER" | |
| fi | |
| fi | |
| echo "::endgroup::" | |
| echo "Checking for non-mirrored require-dev packages, in case this is testing a release branch" | |
| for SLUG in $( jq -r 'keys[]' <<<"$CHANGED" ); do | |
| PKGS=() | |
| readarray -t PKGS < <( jq -r '.extra["non-mirrored-require-dev"] // empty | .[] | . += "=@dev"' "projects/$SLUG/composer.json" ) | |
| if [[ ${#PKGS[@]} -gt 0 ]]; then | |
| echo "::group::Adding packages for $SLUG: ${PKGS[*]}" | |
| # Make sure monorepo repositories entry is present. | |
| JSON=$( jq --tab '.repositories //= [] | if any( .repositories[]; .type == "path" and ( .url | startswith( "../" ) ) and .options?.monorepo? ) then . else .repositories += [ { type: "path", url: "../../packages/*", options: { monorepo: true } } ] end' "projects/$SLUG/composer.json" ) | |
| echo "$JSON" > "projects/$SLUG/composer.json" | |
| # Use --no-install and --ignore-platform-reqs here. Code below (either in .github/files/setup-wordpress-env.sh or the "Run project tests" step) will do a `composer install` or `composer update` as necessary. | |
| composer require --working-dir="projects/$SLUG/" --dev --no-install --ignore-platform-reqs "${PKGS[@]}" | |
| echo "::endgroup::" | |
| fi | |
| done | |
| - name: Setup WordPress environment for plugin tests | |
| env: | |
| API_TOKEN_GITHUB: ${{ secrets.GITHUB_TOKEN }} | |
| CHANGED: ${{ steps.changed.outputs.projects }} | |
| if: steps.changed.outputs.any-plugins == 'true' && matrix.wp != 'none' | |
| run: .github/files/setup-wordpress-env.sh | |
| - name: Run project tests | |
| id: run-tests | |
| env: | |
| FORCE_PACKAGE_TESTS: ${{ matrix.force-package-tests && 'true' || 'false' }} | |
| CHANGED: ${{ steps.changed.outputs.projects }} | |
| run: | | |
| EXIT=0 | |
| declare -A PIDS | |
| PIDS=() | |
| MAXPIDS=$( nproc ) | |
| FAILED=() | |
| mkdir artifacts | |
| [[ "$TEST_SCRIPT" == "test-coverage" ]] && mkdir coverage | |
| for P in composer.json projects/*/*/composer.json; do | |
| if [[ ${#PIDS[@]} -ge $MAXPIDS ]]; then | |
| if ! wait -fn -p PID "${!PIDS[@]}"; then | |
| echo "::error::Tests for ${PIDS[$PID]} failed!" | |
| FAILED+=( "${PIDS[$PID]}" ) | |
| EXIT=1 | |
| fi | |
| echo "Finished ${PIDS[$PID]}" | |
| unset PIDS[$PID] | |
| fi | |
| if [[ "$P" == "composer.json" ]]; then | |
| DIR="." | |
| SLUG="monorepo" | |
| else | |
| DIR="${P%/composer.json}" | |
| SLUG="${DIR#projects/}" | |
| fi | |
| if [[ "${SLUG%%/*}" != "plugins" && "$WP_BRANCH" != 'latest' && "$WP_BRANCH" != 'none' && "$FORCE_PACKAGE_TESTS" != "true" ]]; then | |
| echo "Skipping $SLUG, only plugins run for WP_BRANCH = $WP_BRANCH" | |
| continue | |
| fi | |
| if ! jq --argjson changed "$CHANGED" --arg p "$SLUG" -ne '$changed[$p] // false' > /dev/null; then | |
| echo "Skipping $SLUG, no changes in it or its dependencies" | |
| elif ! jq --arg script "$TEST_SCRIPT" -e '.scripts[$script] // false' "$P" > /dev/null; then | |
| echo "Skipping $SLUG, no test script is defined in composer.json" | |
| elif php -r 'exit( preg_match( "/^>=\\s*(\\d+\\.\\d+)$/", $argv[1], $m ) && version_compare( PHP_VERSION, $m[1], "<" ) ? 0 : 1 );' "$( jq -r '.require.php // ""' "$P" )"; then | |
| echo "Skipping $SLUG, requires PHP $( jq -r '.require.php // ""' "$P" ) but PHP version is $( php -r 'echo PHP_VERSION;' )" | |
| else | |
| if jq --arg script "skip-$TEST_SCRIPT" -e '.scripts[$script] // false' "$P" > /dev/null; then | |
| { composer --working-dir="$DIR" run "skip-$TEST_SCRIPT"; CODE=$?; } || true | |
| if [[ $CODE -eq 3 ]]; then | |
| echo "Skipping tests for $SLUG due to skip-$TEST_SCRIPT script" | |
| continue | |
| elif [[ $CODE -ne 0 ]]; then | |
| echo "::error::Script skip-$TEST_SCRIPT failed to run $CODE!" | |
| FAILED+=( "$SLUG" ) | |
| EXIT=1 | |
| continue | |
| fi | |
| fi | |
| echo "Running tests for $SLUG" | |
| { | |
| # Composer install, if appropriate. Note setup-wordpress-env.sh did it already for plugins. | |
| if [[ "${SLUG%%/*}" != "plugins" && ( "$TEST_SCRIPT" == "test-php" || "$TEST_SCRIPT" == "test-coverage" ) ]]; then | |
| if [[ "$TEST_SCRIPT" == "test-coverage" ]] && | |
| ! jq -e '.scripts["test-php"]' "$DIR/composer.json" &>/dev/null | |
| then | |
| echo "Skipping composer install, assuming test-coverage is only JS because the project has no test-php." | |
| else | |
| if [[ ! -f "$DIR/composer.lock" ]]; then | |
| echo 'No composer.lock, running `composer update`' | |
| composer --working-dir="$DIR" update | |
| elif composer --working-dir="$DIR" check-platform-reqs --lock; then | |
| echo 'Platform reqs pass, running `composer install`' | |
| composer --working-dir="$DIR" install | |
| if [[ "$TEST_SCRIPT" == "test-php" ]] && composer info --locked phpunit/phpunit &>/dev/null; then | |
| echo 'Updating PHPUnit in case a newer version than locked is usable' | |
| composer --working-dir="$DIR" update -W phpunit/phpunit | |
| fi | |
| else | |
| echo 'Platform reqs failed, running `composer update`' | |
| composer --working-dir="$DIR" update | |
| fi | |
| fi | |
| fi | |
| if [[ "${SLUG%%/*}" == "plugins" ]]; then | |
| export WP_TESTS_CONFIG_FILE_PATH="$WORDPRESS_DEVELOP_DIR/wp-tests-config.${SLUG##*/}.php" | |
| fi | |
| mkdir -p "artifacts/$SLUG" | |
| export ARTIFACTS_DIR="$GITHUB_WORKSPACE/artifacts/$SLUG" | |
| if [[ "$TEST_SCRIPT" == "test-coverage" ]]; then | |
| mkdir -p "coverage/$SLUG" | |
| export COVERAGE_DIR="$GITHUB_WORKSPACE/coverage/$SLUG" | |
| fi | |
| FAIL=false | |
| if ! composer run --timeout=0 --working-dir="$DIR" "$TEST_SCRIPT"; then | |
| FAIL=true | |
| fi | |
| # Actions seems to slow down if there are a lot of files, so clean up Composer stuff after each test. | |
| # We don't do it for JS stuff, as that might break things with how JS does package deps. | |
| rm -rf "$DIR/vendor" "$DIR/jetpack_vendor" "$DIR/wordpress" | |
| if $FAIL; then | |
| echo "Tests for $SLUG failed!" | |
| exit 1 | |
| fi | |
| } 2> >( sed -u 's!^!['"$SLUG"'] !' >&2 ) > >( sed -u 's!^!['"$SLUG"'] !' ) & | |
| PIDS[$!]=$SLUG | |
| fi | |
| done | |
| while [[ ${#PIDS[@]} -gt 0 ]]; do | |
| if ! wait -fn -p PID "${!PIDS[@]}"; then | |
| echo "::error::Tests for ${PIDS[$PID]} failed!" | |
| FAILED+=( "${PIDS[$PID]}" ) | |
| EXIT=1 | |
| fi | |
| echo "Finished ${PIDS[$PID]}" | |
| unset PIDS[$PID] | |
| done | |
| if [[ ${#FAILED[@]} -gt 0 ]]; then | |
| echo '' | |
| echo 'The following tests failed:' | |
| printf " - %s\n" "${FAILED[@]}" | |
| fi | |
| exit $EXIT | |
| - name: Process coverage results | |
| id: process-coverage | |
| env: | |
| CHANGED: ${{ steps.changed.outputs.projects }} | |
| if: matrix.script == 'test-coverage' && always() | |
| run: .github/files/coverage-munger/process-coverage.sh | |
| - name: Check for artifacts | |
| id: check-artifacts | |
| # Default for `if` is `success()`, we want this to run always. | |
| if: always() | |
| run: | | |
| [[ -d artifacts ]] && find artifacts -type d -empty -delete | |
| if [[ -d artifacts ]]; then | |
| echo "any=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "any=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Upload artifacts | |
| id: upload-artifacts | |
| if: always() && steps.check-artifacts.outputs.any == 'true' | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: ${{ matrix.artifact }} | |
| path: artifacts | |
| include-hidden-files: true | |
| retention-days: 7 | |
| publish-coverage-data: | |
| name: Publish coverage data | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 # 2025-11-20 Takes about 2 minutes. | |
| needs: run-tests | |
| if: always() && needs.run-tests.outputs.did-coverage == 'true' && github.repository == 'Automattic/jetpack' && ( github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name || github.event_name == 'push' && github.ref == 'refs/heads/trunk' ) | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Get token | |
| id: get_token | |
| if: github.event_name == 'pull_request' | |
| uses: ./.github/actions/gh-app-token | |
| with: | |
| app_id: ${{ secrets.JP_LAUNCH_CONTROL_ID }} | |
| private_key: ${{ secrets.JP_LAUNCH_CONTROL_KEY }} | |
| - name: Setup tools | |
| uses: ./.github/actions/tool-setup | |
| - name: Download coverage artifact | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: 'Code coverage' | |
| path: coverage | |
| - name: Upload coverage results | |
| env: | |
| PR_ID: ${{ github.event_name != 'pull_request' && 'trunk' || github.event.pull_request.number }} | |
| SECRET: ${{ secrets.CODECOV_SECRET }} | |
| STATUS: ${{ needs.run-tests.outputs.coverage-status }} | |
| PR_HEAD: ${{ github.event.pull_request.head.sha }} | |
| POST_MESSAGE_TOKEN: ${{ steps.get_token.outputs.token }} | |
| run: .github/files/coverage-munger/upload-coverage.sh | |
| storybook-test: | |
| name: Storybook tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 # 2025-11-20: Takes about 4 minutes | |
| steps: | |
| - uses: actions/checkout@v6 | |
| # For pull requests, list-changed-projects.sh needs the merge base. | |
| # But it doesn't have to be checked out. | |
| - name: Deepen to merge base | |
| if: github.event_name == 'pull_request' | |
| uses: ./.github/actions/deepen-to-merge-base | |
| with: | |
| checkout: false | |
| - name: Setup tools | |
| uses: ./.github/actions/tool-setup | |
| - name: Monorepo install | |
| run: | | |
| echo "::group::Pnpm" | |
| pnpm install | |
| echo "::endgroup::" | |
| - name: Detect changed projects | |
| id: changed | |
| run: | | |
| CHANGED=$( .github/files/list-changed-projects.sh ) | |
| PROJECTS=$( node -e 'const r = { "js-packages/storybook": true }; for ( const p of require( "./projects/js-packages/storybook/storybook/projects.js" ).projects ) { const m = p.match( /\/projects\/([^/]+\/[^/]+)(?:$|\/)/ ); m && ( r[ m[1] ] = true ); } console.log( JSON.stringify( r ) );' ) | |
| ANY=$( jq --argjson changed "$CHANGED" --argjson projects "$PROJECTS" -n '$changed | with_entries( select( $projects[ .key ] ) ) | any' ) | |
| echo "any=${ANY}" >> "$GITHUB_OUTPUT" | |
| - name: Build storybook | |
| if: steps.changed.outputs.any == 'true' | |
| run: | | |
| pnpm jetpack build -v js-packages/storybook | |
| - name: Install playwright | |
| if: steps.changed.outputs.any == 'true' | |
| run: | | |
| cd projects/js-packages/storybook | |
| pnpm exec playwright install --with-deps chromium | |
| - name: Test storybook | |
| if: steps.changed.outputs.any == 'true' | |
| env: | |
| # Chromium bug, see https://github.com/microsoft/playwright/issues/34046 | |
| LANG: en_US | |
| LC_ALL: en_US | |
| run: | | |
| cd projects/js-packages/storybook | |
| node bin/webserver.mjs | |
| REFERENCE_URL=https://automattic.github.io/jetpack-storybook/ pnpm exec test-storybook -c storybook --url 'http://127.0.0.1:6006/index.html' | |
| # Probably this should be a linting test, but we don't run linting on trunk or release branches. | |
| plugin-deps: | |
| name: Check plugin monorepo dep versions | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 # 2025-11-20: Takes less than a minute. | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup tools | |
| uses: ./.github/actions/tool-setup | |
| with: | |
| node: false | |
| - name: Run check | |
| run: | | |
| if [[ "$GITHUB_EVENT_NAME" == 'push' ]]; then | |
| REF="${GITHUB_REF#refs/heads/}" | |
| elif [[ "$GITHUB_EVENT_NAME" == 'pull_request' || "$GITHUB_EVENT_NAME" == 'pull_request_target' ]]; then | |
| REF="$GITHUB_BASE_REF" | |
| else | |
| echo "::error::Unsupported github event \"$GITHUB_EVENT_NAME\"" | |
| exit 1 | |
| fi | |
| echo "Detected target ref \"$REF\"" | |
| if [[ "$REF" == trunk ]]; then | |
| ARGS=( --dev ) | |
| elif [[ "$REF" == */branch-* ]]; then | |
| ARGS=( --release ) | |
| TMP="$(jq -r --arg P "${REF%%/branch-*}" '.extra["release-branch-prefix"] | if type == "array" then . else [ . ] end | if index( $P ) then input_filename | match( "^projects/plugins/([^/]+)/composer.json$" ).captures[0].string else empty end' projects/plugins/*/composer.json)" | |
| while IFS= read -r LINE; do | |
| ARGS+=( "$LINE" ) | |
| done <<<"$TMP" | |
| else | |
| echo "Unsupported ref \"$REF\", ignoring" | |
| exit 0 | |
| fi | |
| echo "Running tools/check-plugin-monorepo-deps.sh ${ARGS[@]}" | |
| tools/check-plugin-monorepo-deps.sh "${ARGS[@]}" |