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

80 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# QUALITY_GATES.md — executable frontend gates
The single command that runs **every** gate, locally and in CI:
```bash
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`](.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`](.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`.