shoc-frontend-new/QUALITY_GATES.md
Adam Moussa 8b5281d357
Some checks are pending
Frontend checks / Build and test (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
ci(terraform-isolation): re-evaluate the gate on label changes (#177)
* ci(terraform-isolation): re-evaluate the gate on label changes

* test(terraform-isolation): lock the ci.yaml label-event contract

* fix(terraform-isolation): do not treat terraform markdown as a mixed change

* fix(ci): do not skip Frontend checks on isolation label events

* ci(terraform-isolation): run label retriggers in a dedicated workflow

* fix: apply eslint formatting

* fix: apply additional missed eslint formatting
2026-09-10 20:45:49 -04:00

6.8 KiB
Raw Blame History

QUALITY_GATES.md — executable frontend gates

The single command that runs every gate, locally and in CI:

npm run verify

verify chains: format:check → lint → build (tsc -b && vite build) → test (vitest run) → governance. Governance also runs the repository gates: the Terraform import-plan checker tests, the Terraform isolation gate tests, Terraform formatting and validation, and the CDK build, template tests, and synthesis. A task is not done until this is green.

Gate matrix

Gate Command / rule source Enforced by Scope
Formatting npm run format:check (Prettier) verify + lint-staged Whole repo
Lint, zero warnings npm run lint → eslint . --max-warnings=0 verify + CI Governed TS/TSX (eslint.config.js)
Type-check + production build npm run build → tsc -b && vite build verify + CI Whole app
Unit tests npm test → vitest run verify + CI src/test/**, config/**/*.test.ts
Conditional rendering (no : null) no-restricted-syntax in eslint.config.js lint Governed TSX
Boolean-only JSX && seahaven/no-non-boolean-jsx-and (type-aware) in eslint-rules/ lint Governed TSX
Shared Text typography no-restricted-syntax (raw p/h1–h6) + seahaven/no-vp-error-outside-text lint Governed TSX
Hooks correctness eslint-plugin-react-hooks recommended (incl. exhaustive-deps) under zero-warnings lint Governed TS/TSX
Godfile ratchet (file length) scripts/governance-check.mjs + scripts/governance-baseline.json governance src/**, config/** (non-test)
Changed-file maintainability scripts/governance-check.mjs → ESLint (complexity, max-lines-per-function, max-params, max-depth) governance Changed TS/TSX vs base ref
Terraform import-plan contract npm run test:terraform-import-plan → scripts/test-terraform-import-plan-check.py governance + CI Synthetic plan JSON + canonical maps
Terraform isolation gate contract npm run test:terraform-isolation → scripts/check-terraform-isolation.test.mjs governance + CI Changed-file classifier
Terraform formatting/validation npm run test:terraform → scripts/terraform-validate.mjs governance + CI terraform/live/dev
CDK build, tests, synthesis npm run test:infra governance + CI infra/cdk/**, both synth modes
Terraform/app change isolation terraform-isolation.yaml job terraform-isolation → scripts/check-terraform-isolation.mjs CI (PR) Changed files of the PR

No-false-pass guarantees

  • --max-warnings=0 — a warning is a failure. There is no "warning-only" backlog; rules ship green (see AGENTS.md → How to add a convention).
  • Type-aware rules fail closed — seahaven/no-non-boolean-jsx-and reports when type services are unavailable rather than silently claiming safety.
  • Godfile ratchet is monotonic — any new file over the cap, new baseline entry, global cap increase, per-file cap increase, or growth beyond a frozen legacy cap fails. Only cap reductions and entry removals are allowed.
  • Changed-file maintainability fails closed without a valid base — in CI the base ref is derived from GITHUB_BASE_REF (PR) or github.event.before (push). An absent or unresolvable base is a failure, not a pass.
  • Terraform gates never touch live state — terraform init -backend=false -lockfile=readonly and validate run offline; the plan checker is tested against synthetic plan JSON. Real import and controlled-update plans from HCP are migration evidence reviewed by a human before an approved apply (terraform/README.md).
  • The isolation gate re-evaluates on label changes — the terraform-isolation-override label is the only way to merge a mixed Terraform/application PR. .github/workflows/terraform-isolation.yaml runs terraform-isolation on labeled and unlabeled as well as the default pull-request types, so adding or removing the label re-checks the current labels without starting a new Frontend checks run. Removing the label fails a mixed PR that had previously passed with the override.

Where the gates run

  • Locally: npm run verify. lint-staged (via Husky) re-runs ESLint + Prettier on staged files at commit; commitlint enforces Conventional Commits.
  • CI (.github/workflows/ci.yaml): the org reusable workflow (ci-typescript-frontend.yaml, Node 24) runs format/lint/build/tests, and a repo-owned governance job runs npm run verify (with Terraform 1.16.0 installed) so the maintainability ratchets and repository gates are guaranteed from this repository regardless of the reusable workflow.
  • Terraform isolation (.github/workflows/terraform-isolation.yaml): on pull requests, fails when Terraform infrastructure and application code change together. Label add/remove re-runs only this workflow.

Toolchain pin

Node ≥ 22.22.1 (CI uses Node 24); npm 11.16.0 via packageManager (use corepack npm … if your default npm is older). The lockfile is package-lock.json v3; install with npm ci. Governance also needs terraform (CI: 1.16.0; versions.tf accepts >= 1.9.0, < 2.0.0) and python3 (3.10+) on PATH.