shoc-frontend-new/QUALITY_GATES.md
Adam Moussa c96a259365
Some checks failed
Deploy dev content / Deploy shoc-frontend-new-dev through Terraform (push) Has been cancelled
refactor(cd): ship SPA content from GitHub on main (#220)
* ci(cd): convert SPA hosting to handbook HCP and GitHub content CD

Give HCP the bucket and CloudFront with an empty origin path. GitHub owns
bucket-root sync and invalidation so merge-to-main and a human staging tag
can deploy without creating HCP runs. G13 fails PRs that mix terraform/
with deployable application files.

* ci: run Frontend checks and Terraform CI on PRs to main and dev

Match backend 148 so a PR targeting origin/dev still gets the required
checks. Push remains main only.

* refactor(terraform): keep live/dev and live/staging as HCP roots

Leave the adopted working directories in place so this CD PR does not
retarget two live HCP workspaces. Flattening stays a later change.

* style: prettier terraform-validate.mjs

* fix(terraform): pin githubdeploy assume-role policy in import checker

Reject controlled role updates whose trust document is not the rendered
GitHub OIDC policy, matching the bucket-policy pin.
2026-09-18 14:30:20 -04:00

7.1 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: Terraform import-plan checker, Terraform formatting and validation, the HCP run guard, CloudFront verify, workflow shell checks, and G13 (app/Terraform isolation). 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 formatting/validation npm run test:terraform → scripts/terraform-validate.mjs governance + CI terraform/live/dev, terraform/live/staging
HCP run guard npm run test:hcp-run-guard → scripts/test-hcp-run-guard.py governance + CI Workspace invariants + apply reconcile
CloudFront release verify npm run test:cloudfront-release-verify → scripts/test-verify-cloudfront-release.sh governance + CI Stubbed aws/curl
GitHub workflow shell npm run test:github-workflows → scripts/check-github-workflows.sh governance + CI bash -n + actionlint
G13 App/Terraform isolation python3 scripts/check_app_terraform_isolation.py vs GOVERNANCE_BASE governance + CI Deployable app files vs terraform/

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). G13 fails a diff that contains both terraform/ and deployable application files (src/, public/, pages/, config/, index.html, Vite/tsconfig, .env*, or scripts/deploy-web.sh). Workflow, docs, and gate-script changes may travel with either side. Runtime isolation stays: deploy-web.yaml ignores terraform/**, and app-only tags skip HCP when workspace trigger patterns miss.

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 CI (.github/workflows/ci-terraform.yaml): fmt, init -backend=false, validate, import-plan unit tests, and G13 classifier unit tests on terraform/** changes for PRs to main or dev.

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.14.0, < 2.0.0) and python3 (3.10+) on PATH.