ADR-0004: Expand CI and Deployment Quality Gates (Lint, Format, Typecheck, Docs Integrity)
Purpose
Record the decision to expand the Documentation App’s CI and deployment governance beyond “build-only” to include additional quality gates (linting, formatting, type checking, and documentation integrity checks), and to require those checks before production promotion.
This ADR is a portfolio-critical “enterprise signal”: it demonstrates disciplined SDLC controls, reproducibility, and release governance for a public documentation platform.
Scope
In scope
- GitHub Actions checks required on PRs and
main - Vercel Deployment Checks required for promotion to production
- Minimum set of additional gates:
- formatting (Prettier)
- linting (ESLint)
- TypeScript type checks
- documentation integrity (Docusaurus build; broken links as hard failures)
- optional: Markdown lint, spelling, secrets scanning (phased)
Out of scope
- choosing a monorepo-wide “one tool to rule them all” (e.g., migrating to Biome) unless later justified by a separate ADR
- detailed tool configuration contents (captured as implementation tasks and referenced from runbooks/docs)
Prereqs / Inputs
- Decision owner(s): Portfolio maintainer
- Date: 2026-01-07
- Status: Proposed (accept on merge with implemented gates)
- Related ADRs:
- ADR-0001 (Docusaurus platform choice)
- ADR-0002 (autogenerated navigation +
_category_.json) - ADR-0003 (Vercel hosting + previews)
- Related dossier:
docs/60-projects/documentation-app/testing.mddocs/60-projects/documentation-app/deployment.md
- Current baseline assumptions:
- pnpm is the package manager; lockfile is committed
- build gate exists (
pnpm build) and must fail on broken links - PR-only merges to
mainare required
Decision Record
Title
ADR-0004: Expand CI and Deployment Quality Gates (Lint, Format, Typecheck, Docs Integrity)
Context
The Documentation App is both:
- a production-like public system, and
- a core portfolio artifact that must demonstrate enterprise delivery discipline.
As content and configuration scale (more docs, more automation, more contributor/agent activity), “build-only” gating is necessary but insufficient:
- Formatting drift increases review friction and reduces credibility.
- Linting/type errors in Docusaurus config/theme code can break builds or cause subtle runtime issues.
- Inconsistent Markdown practices and structural errors increase navigation entropy and broken references.
- Vercel can create deployments even when GitHub checks are failing unless promotion is gated.
We need a coherent, enforceable quality gate set that:
- prevents regressions early (PR time)
- produces deterministic, reproducible builds
- scales to AI-assisted authoring without sacrificing quality
- gates production promotion on verified checks
Decision
Implement an expanded CI quality gate framework and require these checks before production promotion:
A) GitHub Actions (required on PR + main)
Minimum required jobs:
-
Quality job (fast fail)
pnpm lint(ESLint)pnpm format:check(Prettier check, no writes)pnpm typecheck(TypeScript type checking)- Optional (phase 2):
pnpm lint:md(Markdown lint)
-
Build job (hard integrity gate)
pnpm build(must fail on broken links / structural issues)
B) Vercel Deployment Checks (required for production promotion)
Require the corresponding GitHub checks (at minimum):
ci / qualityci / build
Production domains must not be assigned (“promoted”) until checks pass.
Alternatives considered
-
Build-only gate (status quo)
- Pros: minimal time, minimal setup
- Cons: allows format drift, type/lint issues, inconsistent docs hygiene; more review burden; lower enterprise credibility
- Rejected because: does not scale to enterprise documentation scope or AI-assisted contributions.
-
Pre-commit hooks only (no CI enforcement)
- Pros: faster developer feedback
- Cons: unenforceable; contributors/agents can bypass; inconsistent in CI; weaker evidence posture
- Rejected because: enterprise posture requires server-side enforcement.
-
Single “mega job” in CI
- Pros: simplest workflow
- Cons: slow feedback; harder to parallelize; harder to reason about required checks in Vercel promotion
- Rejected because: we want a clear split between “quality” (fast) and “build integrity” (hard gate).
-
Adopt Biome (formatter + linter) instead of ESLint/Prettier
- Pros: speed, consolidation
- Cons: migration effort; ecosystem/tooling differences; potential mismatch with Docusaurus/React conventions already expected
- Deferred: may be reconsidered later via a dedicated ADR if the repo grows significantly.
Consequences
Positive consequences
- Stronger, more credible enterprise SDLC posture:
- style consistency, reduced review overhead
- type correctness in configuration/theme code
- earlier detection of errors before they reach production
- Improved safety for AI-assisted contributions:
- deterministic gates reduce “silent drift”
- Production governance strengthens:
- Vercel promotion is gated on verified checks
Negative consequences / tradeoffs
- CI runtime increases (more checks)
- Tooling maintenance required:
- eslint/prettier/typecheck configs must be kept current
- Contributors must follow consistent local tooling setup (documented in contributor guides)
Security impact
- Reduced risk of unsafe/unstable build changes merging
- Provides a platform for adding additional security controls later (e.g., secret scanning gate, dependency auditing gate)
Operational impact
- Runbooks must reflect new failure modes:
- “quality job failing” becomes a deploy blocker
- Triage paths must distinguish:
- formatting/lint failures vs build/link failures
Implementation notes (high-level)
1) Add canonical scripts in package.json
Required scripts (names are part of the “contract”):
lint→ ESLintformat:check→ Prettier check (no writes)format:write→ Prettier write (local use)typecheck→tsc --noEmitbuild→ Docusaurus build (already present)
Optional phase 2:
lint:md→ Markdown lint (markdownlint-cli2 or equivalent)lint:links→ external link checker (later; avoid gating early due to flakiness)
2) Add minimal configuration files (if not already present)
- ESLint config (flat or legacy—choose one and standardize)
- Prettier config
- TypeScript config suitable for
tsc --noEmit(if Docusaurus TS config exists, reuse it) - Editor settings (optional) for consistent formatting in VS Code
3) Update GitHub Actions workflow
- Add a
qualityjob and keepbuildjob. - Ensure both run on:
pull_requestpushtomain
4) Update Vercel Deployment Checks
- Import the two checks as requirements for production promotion:
ci / qualityci / build
5) Update documentation + runbooks (required for acceptance)
- Dossier:
docs/60-projects/documentation-app/testing.md(describe gates + commands)docs/60-projects/documentation-app/deployment.md(describe promotion gating)
- Runbooks:
rbk-docs-deploy.md(checks required before promotion)rbk-docs-rollback.md(roll back via revert; note checks behavior)rbk-docs-broken-links-triage.md(build gate triage; add pointer for “quality job failing”)
- Add a short “CI Gates Policy” note under
docs/30-devops-platform/ci-cd/(or equivalent) if that domain exists.
Validation / Expected outcomes
This decision is successful when:
- On every PR:
ci / qualitypasses (lint + format:check + typecheck)ci / buildpasses (Docusaurus build, broken links fail)
- On
main:- the same checks run and pass deterministically
- On Vercel:
- production promotion is blocked until required checks pass
- Contributor experience:
- local commands exist and are documented
- failures are actionable and mapped to runbooks
Failure modes / Troubleshooting
- Format check fails frequently:
- ensure Prettier is configured and
format:writeexists; educate contributors; do not relax the gate.
- ensure Prettier is configured and
- Lint rules too noisy:
- tune rules carefully and record major policy changes in a follow-up ADR if necessary.
- Typecheck fails due to incomplete TS config:
- refine tsconfig to match Docusaurus project layout; keep typecheck scoped to repo TS sources.
- Vercel waits indefinitely for checks:
- ensure workflows run on
pushtomain(not PR-only) and that check names are stable.
- ensure workflows run on
References
- Documentation App dossier:
docs/60-projects/documentation-app/testing.mddocs/60-projects/documentation-app/deployment.md
- Ops runbooks:
docs/50-operations/runbooks/rbk-docs-deploy.mddocs/50-operations/runbooks/rbk-docs-rollback.mddocs/50-operations/runbooks/rbk-docs-broken-links-triage.md
- Related ADRs:
docs/10-architecture/adr/adr-0001-adopt-docusaurus-for-portfolio-docs.mddocs/10-architecture/adr/adr-0002-navigation-governance-autogenerated-and-category-metadata.mddocs/10-architecture/adr/adr-0003-hosting-vercel-with-preview-deployments.md