name: Frontend checks on: pull_request: branches: [main, dev] # The merge queue builds main plus the queued pull requests on a temporary # branch and only counts checks that ran on the merge_group event. merge_group: push: branches: [main] workflow_dispatch: {} permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: static: name: static runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" cache: npm - run: npm ci - run: npm run format:check - run: npm run lint build: name: build runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" cache: npm - run: npm ci - run: npm run build unit: name: unit runs-on: ubuntu-latest strategy: fail-fast: false matrix: shard: [1, 2, 3, 4] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" cache: npm - run: npm ci - run: npm test -- --shard=${{ matrix.shard }}/4 visual: name: Visual regression runs-on: ubuntu-latest container: mcr.microsoft.com/playwright:v1.61.1-noble steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" cache: npm - run: npm ci - run: npm run test:e2e:visual - name: Upload visual diff artifacts if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: visual-regression-diffs path: | test-results/visual playwright-report-visual if-no-files-found: ignore retention-days: 14 governance: # Repo-owned gates: godfile ratchet, changed-file maintainability, # Terraform fmt/validate, import-plan guard, HCP run guard, CloudFront # verify, GitHub workflow shell, isolation classifier tests, and live G13 # (pull_request, merge_group per queued PR, and local). Format, lint, build, # and unit tests run # in the parallel jobs above, not here. # # GOVERNANCE_BASE points the changed-file gate at the right diff: # PR -> the PR target branch (origin/) # merge group -> the group's own base (github.event.merge_group.base_sha) # push-> the previous commit on the branch (github.event.before) # manual -> main, for exact-head recovery runs runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - name: Resolve governance comparison ref id: governance-ref shell: bash env: EVENT_NAME: ${{ github.event_name }} EVENT_BEFORE: ${{ github.event.before }} PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} MERGE_GROUP_BASE_SHA: ${{ github.event.merge_group.base_sha }} run: | set -euo pipefail if [[ "${EVENT_NAME}" == "pull_request" ]]; then base="${PR_BASE_SHA}" elif [[ "${EVENT_NAME}" == "merge_group" && -n "${MERGE_GROUP_BASE_SHA}" ]]; then base="${MERGE_GROUP_BASE_SHA}" elif [[ "${EVENT_NAME}" == "push" && -n "${EVENT_BEFORE}" && ! "${EVENT_BEFORE}" =~ ^0+$ ]]; then base="${EVENT_BEFORE}" else base="origin/main" fi printf 'base=%s\n' "${base}" >> "${GITHUB_OUTPUT}" - name: Set up Terraform # Same minor as the HCP workspace (1.16.x) so fmt/validate see what # the remote run will see. uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1 with: terraform_version: "1.16.0" terraform_wrapper: false - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" cache: npm - name: Install actionlint env: ACTIONLINT_VERSION: "1.7.12" ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 run: | set -euo pipefail curl -fsSL -o actionlint.tar.gz \ "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" echo "${ACTIONLINT_SHA256} actionlint.tar.gz" | sha256sum -c - tar -xzf actionlint.tar.gz actionlint sudo mv actionlint /usr/local/bin/actionlint - run: npm ci - run: npm run governance env: GOVERNANCE_BASE: ${{ steps.governance-ref.outputs.base }} ci-complete: name: ci-complete if: always() needs: [static, build, unit, visual, governance] runs-on: ubuntu-latest steps: - name: All required jobs passed shell: bash env: RESULTS: ${{ join(needs.*.result, ' ') }} run: | set -euo pipefail failed=0 for result in ${RESULTS}; do if [[ "${result}" != "success" ]]; then failed=1 fi done if [[ "${failed}" -ne 0 ]]; then echo "Required jobs did not all succeed: ${RESULTS}" exit 1 fi