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 }} test-jobs: ${{ steps.project-jobs.outputs.test-jobs }} steps: - uses: 'actions/checkout@v3' 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@v3' 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-test-jobs: name: 'Test - ${{ matrix.projectName }} - ${{ matrix.name }}' runs-on: 'ubuntu-20.04' needs: 'project-jobs' if: ${{ needs.project-jobs.outputs.test-jobs != '[]' }} strategy: fail-fast: false matrix: include: ${{ fromJSON( needs.project-jobs.outputs.test-jobs ) }} steps: - uses: 'actions/checkout@v3' 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: '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 }}' 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 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-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-test-jobs.result }}" if [[ $result != "success" && $result != "skipped" ]]; then echo "One or more test jobs have failed." exit 1 fi echo "All jobs have completed successfully."