From c28153f443c742a9c829e33f71570d4b6231b567 Mon Sep 17 00:00:00 2001 From: T3 Code Date: Wed, 7 Oct 2026 16:41:01 +0200 Subject: [PATCH] ci(workflows): consolidate to single ci.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four separate workflow files (build.yml, lint.yml, tests.yml, types.yml) plus a partial ci.yml had drifted into a confusing split: each PR showed only 4-5 of the 9 actual checks at a glance, and the changeset check was hidden behind a separate file that did not run on push. Consolidate everything into a single ci.yml with 5 jobs (build, lint, test with 3-Node matrix, type-check with 3-Node matrix, changeset required on PRs to staging). The view in the GitHub Actions UI now matches what 'gh pr checks' reports: all 9 checks visible in one place, named consistently. Release workflow (release.yml) stays separate — different trigger (workflow_dispatch / PR merge to main), different permissions, and a different lifetime (one-shot per release rather than per-commit). --- .github/workflows/ci.yml | 168 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c47d95..5605560 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,178 @@ name: ci on: + push: + branches: [main, staging, dev] pull_request: - branches: [staging] + branches: [main, staging, dev] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: + # ============================================================================ + # Build + # ============================================================================ + build: + name: Build + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'pnpm' + + - name: Cache Turborepo + uses: actions/cache@v4 + with: + path: .turbo + key: turbo-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + + - name: Install dependencies + run: pnpm install + + - name: Run build + run: pnpm build + + # ============================================================================ + # Lint + # ============================================================================ + lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'pnpm' + + - name: Cache Turborepo + uses: actions/cache@v4 + with: + path: .turbo + key: turbo-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + + - name: Install dependencies + run: pnpm install + + - name: Run prettier check + run: pnpm format:check + + - name: Run lint + run: pnpm lint + + # ============================================================================ + # Tests (matrix: Node 20, 22, 24) + # ============================================================================ + test: + name: Tests (node ${{ matrix.node }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + node: [20, 22, 24] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: 'pnpm' + + - name: Cache Turborepo + uses: actions/cache@v4 + with: + path: .turbo + key: turbo-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + + - name: Install dependencies + run: pnpm install + + - name: Run tests + run: pnpm test + + # Apps/web SEO regression suite (apps/web/tests/seo). Runs after the + # root test pipeline so we benefit from the existing install cache. + # The suite is a pure-Vitest run; no real Next build is required. + - name: Run apps/web SEO tests + run: pnpm --filter web test:run + + # Apps/web has a test-specific tsconfig that enables + # `allowImportingTsExtensions` so tests can target routes whose + # directory names contain a dot (e.g. `llms.txt/route.ts`). The + # production tsconfig does not enable it, so we run type-check:test + # explicitly. The regular `pnpm turbo type-check` is run on the + # rest of the workspace by the `Type Check` job below. + - name: Type-check apps/web test suite + run: pnpm --filter web type-check:test + + # ============================================================================ + # Type Check (matrix: Node 20, 22, 24) + # ============================================================================ + type-check: + name: Type Check (node ${{ matrix.node }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + node: [20, 22, 24] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: 'pnpm' + + - name: Cache Turborepo + uses: actions/cache@v4 + with: + path: .turbo + key: turbo-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + + - name: Install dependencies + run: pnpm install + + - name: Run type check + run: pnpm turbo type-check + + # ============================================================================ + # Changeset required (PRs to staging only) + # ============================================================================ changeset-check: name: Changeset required + if: github.event_name == 'pull_request' && github.base_ref == 'staging' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4