Repository navigation
docs(feature-map): keep the page's sources in the repo; npm run docs:feature-map #904
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: Build Gate | |
| # Correctness gates for every change, run before it can reach main. | |
| # | |
| # These same checks already existed in release-gate.yml, but that workflow only | |
| # triggers on a `v*` tag push — so nothing ran on a pull request or on a push to | |
| # main. Two green PRs whose merge result did not compile were merged that way, | |
| # and the breakage was only found later, locally. This workflow closes that gap: | |
| # the gates run on the merge result, not just at release time. | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| # A new push supersedes an in-flight run for the same ref. | |
| concurrency: | |
| group: build-gate-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| typecheck: | |
| # A version-bump commit changes four package.json version fields and | |
| # nothing else, so there is nothing here for it to check. It used to carry | |
| # `[skip ci]` for this, but that marker also suppresses the *tag* push that | |
| # rides on the same commit, which silently disabled every release — see | |
| # version-bump.yml. Skipping by message keeps the saving without that cost. | |
| # Guarded on event_name so pull_request runs are never skipped. | |
| if: "${{ github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'chore: bump version') }}" | |
| name: Typecheck | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| # npm 10 (what Node 22 ships) cannot resolve this workspace graph | |
| # without a lockfile — arborist dies in #loadPeerSet on vitest with | |
| # "Cannot read properties of null (reading 'edgesOut')". npm 11 does | |
| # it fine. Verified on a clean clone at Node 22.23.1. | |
| - run: npm i -g npm@11 | |
| - run: npm ci --ignore-scripts | |
| # apps/web's tsconfig covers the frontend, the backend, and — through the | |
| # workspace path aliases — packages/sql. apps/e2e's covers the Playwright | |
| # suite, where byTestId() turns a selector for a removed test ID into a | |
| # compile error. | |
| - run: npm run typecheck | |
| unit-tests: | |
| # A version-bump commit changes four package.json version fields and | |
| # nothing else, so there is nothing here for it to check. It used to carry | |
| # `[skip ci]` for this, but that marker also suppresses the *tag* push that | |
| # rides on the same commit, which silently disabled every release — see | |
| # version-bump.yml. Skipping by message keeps the saving without that cost. | |
| # Guarded on event_name so pull_request runs are never skipped. | |
| if: "${{ github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'chore: bump version') }}" | |
| name: Unit tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| # npm 10 (what Node 22 ships) cannot resolve this workspace graph | |
| # without a lockfile — arborist dies in #loadPeerSet on vitest with | |
| # "Cannot read properties of null (reading 'edgesOut')". npm 11 does | |
| # it fine. Verified on a clean clone at Node 22.23.1. | |
| - run: npm i -g npm@11 | |
| - run: npm ci --ignore-scripts | |
| - run: npx vitest run | |
| frontend-build: | |
| # A version-bump commit changes four package.json version fields and | |
| # nothing else, so there is nothing here for it to check. It used to carry | |
| # `[skip ci]` for this, but that marker also suppresses the *tag* push that | |
| # rides on the same commit, which silently disabled every release — see | |
| # version-bump.yml. Skipping by message keeps the saving without that cost. | |
| # Guarded on event_name so pull_request runs are never skipped. | |
| if: "${{ github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'chore: bump version') }}" | |
| name: Frontend build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| # npm 10 (what Node 22 ships) cannot resolve this workspace graph | |
| # without a lockfile — arborist dies in #loadPeerSet on vitest with | |
| # "Cannot read properties of null (reading 'edgesOut')". npm 11 does | |
| # it fine. Verified on a clean clone at Node 22.23.1. | |
| - run: npm i -g npm@11 | |
| - run: npm ci --ignore-scripts | |
| # Typecheck and tests both passed while `vite build` was broken for | |
| # months: a dependency's `exports` map changed and only the bundler's | |
| # resolver could see it. Nothing else in this workflow builds the | |
| # frontend, which is the artifact users actually run. | |
| - run: npm run build -w @foxschema/web | |
| # What a first visit downloads (index.html and the files it names). Over | |
| # budget means something heavy became a static import on the first page; | |
| # the report lists the largest files. Was 398 KB gzip before on-demand | |
| # loading (2026-10-05), 210 KB after #481, 140 KB after the second round. | |
| - run: node scripts/bundle/first-load.mjs apps/web/dist --budget-gzip-kb=170 | |
| lint: | |
| # A version-bump commit changes four package.json version fields and | |
| # nothing else, so there is nothing here for it to check. It used to carry | |
| # `[skip ci]` for this, but that marker also suppresses the *tag* push that | |
| # rides on the same commit, which silently disabled every release — see | |
| # version-bump.yml. Skipping by message keeps the saving without that cost. | |
| # Guarded on event_name so pull_request runs are never skipped. | |
| if: "${{ github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'chore: bump version') }}" | |
| name: ESLint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| # npm 10 (what Node 22 ships) cannot resolve this workspace graph | |
| # without a lockfile — arborist dies in #loadPeerSet on vitest with | |
| # "Cannot read properties of null (reading 'edgesOut')". npm 11 does | |
| # it fine. Verified on a clean clone at Node 22.23.1. | |
| - run: npm i -g npm@11 | |
| - run: npm ci --ignore-scripts | |
| # Everything: security rules are errors, quality rules are warnings. | |
| - run: npx eslint . | |
| # Security rules only, zero tolerance. This is the gate that was defined | |
| # in package.json but never run here, and could not have passed if it | |
| # had been — it counted quality warnings too. It runs its own config now. | |
| - run: npm run lint:security | |
| # Production dependencies only, at `high`, and blocking. The threshold was | |
| # `critical`, which meant the two HIGH advisories in the ibm_db -> adm-zip | |
| # chain never failed anything and nobody was told; the `adm-zip: 0.6.1` | |
| # override plus a committed lockfile clears them, so this is a real gate. | |
| - run: npm run audit:security |