name: 'CI' on: pull_request: push: branches: - 'trunk' - 'release/*' concurrency: group: '${{ github.workflow }}-${{ github.ref }}' cancel-in-progress: true jobs: project-jobs: # Since this is a monorepo, not every pull request or change is going to impact every project. # Instead of running CI tasks on all projects indiscriminately, we use a command to detect # which projects have changed and what kind of change occurred. This lets us build the # matrices that we can use to run CI tasks only on the projects that need them. name: 'Build Project Jobs' runs-on: 'ubuntu-20.04' outputs: lint-jobs: ${{ steps.project-jobs.outputs.lint-jobs }} default-test-jobs: ${{ steps.project-jobs.outputs.default-test-jobs }} e2e-test-jobs: ${{ steps.project-jobs.outputs.e2e-test-jobs }} api-test-jobs: ${{ steps.project-jobs.outputs.api-test-jobs }} performance-test-jobs: ${{ steps.project-jobs.outputs.performance-test-jobs }} steps: - uses: 'actions/checkout@v4' name: 'Checkout' with: fetch-depth: 0 - uses: './.github/actions/setup-woocommerce-monorepo' name: 'Setup Monorepo' with: php-version: false # We don't want to waste time installing PHP since we aren't using it in this job. - uses: actions/github-script@v6 name: 'Build Matrix' id: 'project-jobs' with: script: | let baseRef = ${{ toJson( github.base_ref ) }}; if ( baseRef ) { baseRef = `--base-ref origin/${ baseRef }`; } const child_process = require( 'node:child_process' ); child_process.execSync( `pnpm utils ci-jobs ${ baseRef }` ); project-lint-jobs: name: 'Lint - ${{ matrix.projectName }}' runs-on: 'ubuntu-20.04' needs: 'project-jobs' if: ${{ needs.project-jobs.outputs.lint-jobs != '[]' }} strategy: fail-fast: false matrix: include: ${{ fromJSON( needs.project-jobs.outputs.lint-jobs ) }} steps: - uses: 'actions/checkout@v4' name: 'Checkout' with: fetch-depth: 0 - uses: './.github/actions/setup-woocommerce-monorepo' name: 'Setup Monorepo' id: 'setup-monorepo' with: install: '${{ matrix.projectName }}...' build: '${{ matrix.projectName }}' - name: 'Lint' run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.command }}' project-default-test-jobs: name: 'Test - ${{ matrix.projectName }} - ${{ matrix.name }}' runs-on: 'ubuntu-20.04' needs: 'project-jobs' if: ${{ needs.project-jobs.outputs.default-test-jobs != '[]' }} strategy: fail-fast: false matrix: include: ${{ fromJSON( needs.project-jobs.outputs.default-test-jobs ) }} steps: - uses: 'actions/checkout@v4' name: 'Checkout' - uses: './.github/actions/setup-woocommerce-monorepo' name: 'Setup Monorepo' id: 'setup-monorepo' with: install: '${{ matrix.projectName }}...' build: '${{ matrix.projectName }}' - name: 'Prepare Test Environment' id: 'prepare-test-environment' if: ${{ matrix.testEnv.shouldCreate }} env: ${{ matrix.testEnv.envVars }} run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.testEnv.start }}' - name: 'Test' run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.command }}' project-e2e-test-jobs: name: 'E2E - ${{ matrix.name }}' runs-on: 'ubuntu-20.04' needs: 'project-jobs' if: ${{ needs.project-jobs.outputs.e2e-test-jobs != '[]' }} strategy: fail-fast: false matrix: include: ${{ fromJSON( needs.project-jobs.outputs.e2e-test-jobs ) }} steps: - uses: 'actions/checkout@v4' name: 'Checkout' - uses: './.github/actions/setup-woocommerce-monorepo' name: 'Setup Monorepo' id: 'setup-monorepo' with: install: '${{ matrix.projectName }}...' build: '${{ matrix.projectName }}' - name: 'Prepare Test Environment' id: 'prepare-test-environment' if: ${{ matrix.testEnv.shouldCreate }} run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.testEnv.start }}' - name: 'Run tests' run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.command }}' - name: 'Upload artifacts' if: ${{ always() }} uses: actions/upload-artifact@v4 with: name: all-blob-e2e-reports-${{ matrix.shardNumber }} path: ${{ matrix.projectPath }}/tests/e2e-pw/test-results retention-days: 1 compression-level: 9 project-api-test-jobs: name: 'API - ${{ matrix.name }}' runs-on: 'ubuntu-20.04' needs: 'project-jobs' if: ${{ needs.project-jobs.outputs.api-test-jobs != '[]' }} strategy: fail-fast: false matrix: include: ${{ fromJSON( needs.project-jobs.outputs.api-test-jobs ) }} steps: - uses: 'actions/checkout@v4' name: 'Checkout' - uses: './.github/actions/setup-woocommerce-monorepo' name: 'Setup Monorepo' id: 'setup-monorepo' with: install: '${{ matrix.projectName }}...' build: '${{ matrix.projectName }}' - name: 'Prepare Test Environment' id: 'prepare-test-environment' if: ${{ matrix.testEnv.shouldCreate }} run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.testEnv.start }}' - name: 'Run tests' run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.command }}' - name: 'Upload artifacts' if: ${{ always() }} uses: actions/upload-artifact@v4 with: name: all-blob-api-reports-${{ matrix.shardNumber }} path: ${{ matrix.projectPath }}/tests/api-core-tests/test-results/allure-results retention-days: 1 compression-level: 9 project-performance-test-jobs: name: 'Performance - ${{ matrix.name }}' runs-on: 'ubuntu-20.04' needs: 'project-jobs' if: ${{ needs.project-jobs.outputs.performance-test-jobs != '[]' }} strategy: fail-fast: false matrix: include: ${{ fromJSON( needs.project-jobs.outputs.performance-test-jobs ) }} env: WP_ARTIFACTS_PATH: ${{ github.workspace }}/artifacts steps: - uses: 'actions/checkout@v4' name: 'Checkout' - uses: './.github/actions/setup-woocommerce-monorepo' name: 'Setup Monorepo' id: 'setup-monorepo' with: install: '${{ matrix.projectName }}...' build: '${{ matrix.projectName }}' - name: 'Prepare Test Environment' id: 'prepare-test-environment' if: ${{ matrix.testEnv.shouldCreate }} run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.testEnv.start }}' - name: 'Run tests' env: CODEVITALS_PROJECT_TOKEN: ${{ secrets.CODEVITALS_PROJECT_TOKEN }} run: 'pnpm --filter="${{ matrix.projectName }}" ${{ matrix.command }}' - name: 'Archive metrics results' if: ${{ success() && matrix.name == 'Metrics' }} uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: metrics-results path: ${{ env.WP_ARTIFACTS_PATH }}/*.performance-results*.json evaluate-project-jobs: # In order to add a required status check we need a consistent job that we can grab onto. # Since we are dynamically generating a matrix for the project jobs, however, we can't # rely on any specific job being present. We can get around this limitation by # using a job that runs after all the others and either passes or fails based # on the results of the other jobs in the workflow. name: 'Evaluate Project Job Statuses' runs-on: 'ubuntu-20.04' needs: [ 'project-jobs', 'project-lint-jobs', 'project-default-test-jobs', 'project-e2e-test-jobs', 'project-api-test-jobs' ] if: ${{ always() }} steps: - name: 'Evaluation' run: | result="${{ needs.project-jobs.result }}" if [[ $result != "success" && $result != "skipped" ]]; then echo "An error occurred generating the CI jobs." exit 1 fi result="${{ needs.project-lint-jobs.result }}" if [[ $result != "success" && $result != "skipped" ]]; then echo "One or more lint jobs have failed." exit 1 fi result="${{ needs.project-default-test-jobs.result }}" if [[ $result != "success" && $result != "skipped" ]]; then echo "One or more test jobs have failed." exit 1 fi result="${{ needs.project-e2e-test-jobs.result }}" if [[ $result != "success" && $result != "skipped" ]]; then echo "One or more e2e test jobs have failed." exit 1 fi result="${{ needs.project-api-test-jobs.result }}" if [[ $result != "success" && $result != "skipped" ]]; then echo "One or more api test jobs have failed." exit 1 fi echo "All jobs have completed successfully." e2e-test-reports: name: 'Report e2e tests results' needs: [ project-e2e-test-jobs ] if: ${{ ! cancelled() && needs.project-e2e-test-jobs.result != 'skipped' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 'Install Allure CLI' env: DESTINATION_PATH: ../ run: ./.github/workflows/scripts/install-allure.sh - name: 'Download blob reports from artifacts' uses: actions/download-artifact@v4 with: path: ./out pattern: all-blob-e2e-reports-* run-id: project-e2e-test-jobs merge-multiple: true - name: 'Generate Allure report' id: generate_allure_report run: allure generate --clean ./out/allure-results --output ./out/allure-report - name: 'Archive reports' uses: actions/upload-artifact@v4 with: name: e2e-test-report path: ./out if-no-files-found: ignore retention-days: 5 - name: 'Send workflow dispatch' env: GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} RUN_ID: ${{ github.run_id }} run: | if [ "$GITHUB_EVENT_NAME" == pull_request ]; then gh workflow run publish-test-reports-pr.yml \ -f run_id=$RUN_ID \ -f e2e_artifact=e2e-test-report \ -f pr_number=$PR_NUMBER \ -f commit_sha=$GITHUB_SHA \ -f s3_root=public \ --repo woocommerce/woocommerce-test-reports else gh workflow run publish-test-reports-trunk-merge.yml \ -f run_id=$RUN_ID \ -f artifact=e2e-test-report \ -f pr_number=$PR_NUMBER \ -f commit_sha=$GITHUB_SHA \ -f test_type="e2e" \ --repo woocommerce/woocommerce-test-reports fi - name: 'Send Slack notification' if: github.event_name != 'pull_request' uses: automattic/action-test-results-to-slack@v0.3.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} slack_token: ${{ secrets.E2E_SLACK_TOKEN }} slack_channel: ${{ secrets.E2E_TRUNK_SLACK_CHANNEL }} playwright_report_path: ./out/test-results-*.json playwright_output_dir: ./out/results-data api-test-reports: name: 'Report API tests results' needs: [ project-api-test-jobs ] if: ${{ ! cancelled() && needs.project-api-test-jobs.result != 'skipped'}} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 'Install Allure CLI' env: DESTINATION_PATH: ../ run: ./.github/workflows/scripts/install-allure.sh - name: 'Download blob reports from artifacts' uses: actions/download-artifact@v4 with: path: ./out/allure-results pattern: all-blob-api-reports-* run-id: project-api-test-jobs merge-multiple: true - name: 'Generate Allure report' id: generate_allure_report run: allure generate --clean ./out/allure-results --output ./out/allure-report - name: 'Archive reports' uses: actions/upload-artifact@v4 with: name: api-test-report path: ./out if-no-files-found: ignore retention-days: 5 - name: 'Publish reports' env: GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} RUN_ID: ${{ github.run_id }} run: | if [ "$GITHUB_EVENT_NAME" == pull_request ]; then gh workflow run publish-test-reports-pr.yml \ -f run_id=$RUN_ID \ -f api_artifact=api-test-report \ -f pr_number=$PR_NUMBER \ -f commit_sha=$GITHUB_SHA \ -f s3_root=public \ --repo woocommerce/woocommerce-test-reports else gh workflow run publish-test-reports-trunk-merge.yml \ -f run_id=$RUN_ID \ -f artifact=api-test-report \ -f pr_number=$PR_NUMBER \ -f commit_sha=$GITHUB_SHA \ -f test_type="api" \ --repo woocommerce/woocommerce-test-reports fi - name: 'Send Slack notification' if: github.event_name != 'pull_request' uses: automattic/action-test-results-to-slack@v0.3.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} slack_token: ${{ secrets.E2E_SLACK_TOKEN }} slack_channel: ${{ secrets.E2E_TRUNK_SLACK_CHANNEL }}