Skip to content

CI and Local Gates

Required local and CI verification gates for projects that follow these standards. Agents MUST run every applicable gate before marking work complete.

Agent Quick Rules {#agent-quick-rules}

  • MUST run backend build and test before marking backend work complete.
  • MUST run pnpm lint, type-check, test, and build for every changed frontend app.
  • MUST use pnpm install --frozen-lockfile in CI.
  • MUST verify OpenAPI freshness when generated API types are committed.
  • SHOULD run node scripts/validate-domain-docs.mjs when domain docs change.

Full convention: docs/conventions/shared/ci.md


0. pnpm Workspace Setup

All frontend apps and packages share a single pnpm workspace. The pnpm-lock.yaml and pnpm-workspace.yaml files live at the repository root. Individual app directories have their own package.json but no separate lockfile.

Install from the root to populate the shared node_modules:

Terminal window
pnpm install

Running pnpm install from an app subdirectory also works: pnpm walks up to find the workspace root automatically.

In CI, use --frozen-lockfile to fail if the lockfile is out of sync:

Terminal window
pnpm install --frozen-lockfile

When running the Aspire AppHost, run pnpm install from the workspace root before starting the AppHost. The WithPnpm() call in the AppHost triggers pnpm install in each app’s subdirectory, which resolves back to the workspace root.


Monorepos SHOULD expose common workflows from root package.json:

ScriptCommand purpose
dev:aspireStart AppHost
dev:apiRun WebApi standalone (manual path)
dev:web / dev:adminRun individual Next.js apps
db:migratedotnet ef database update with standard project paths
db:migrate:addWrapper for dotnet ef migrations add

Document which path (Aspire vs manual) each script targets in the project development guide.

See also docs/conventions/shared/local-ide-setup.md for VS Code / Cursor debug configs.


1. Required CI Gates

Every pull request MUST run:

GateCommand
Backend builddotnet build apps/api/{ProjectName}.slnx --configuration Release
Backend testsdotnet test apps/api/{ProjectName}.slnx --configuration Release --no-build
Vulnerable NuGet packagesdotnet list apps/api/src/{ProjectName}.slnx package --vulnerable
Frontend installpnpm install --frozen-lockfile
Frontend lintpnpm lint
Frontend type checkpnpm type-check
Frontend unit testspnpm test
Frontend buildpnpm build
Frontend auditpnpm audit
Playwright E2Epnpm exec playwright test --config apps/web/playwright.config.ts
OpenAPI freshnessRegenerate spec and types, then git diff --exit-code on artifacts

Skip frontend gates when the project has no frontend. Skip Playwright when no apps/web/e2e/ exists yet (document in project ADR). Skip OpenAPI freshness when no generated frontend API types are committed.


2. OpenAPI Freshness Gate

Terminal window
# 1. Build (generates openapi.json into the WebApi build output via Microsoft.Extensions.ApiDescription.Server)
dotnet build apps/api/{ProjectName}.slnx --configuration Release
# 2. Copy the generated spec
cp apps/api/src/{ProjectName}.WebApi/bin/Release/net10.0/openapi.json packages/api-types/openapi.json
# 3. Regenerate TypeScript types
pnpm --filter @myproject/api-types generate:api-types
# 4. Fail if the generated files differ from what was committed
git diff --exit-code packages/api-types/openapi.json packages/api-types/src/api.d.ts

Build-time generation requires Microsoft.Extensions.ApiDescription.Server in the WebApi project. See docs/conventions/backend/api-layer.md for the MSBuild configuration.

If the diff is non-empty, the PR forgot to commit regenerated API artifacts.


3. Example GitHub Actions Workflow

Use docs/templates/config/ci-workflow.yml as the canonical workflow template. It includes backend gates, frontend gates, OpenAPI freshness, Playwright, and optional standards submodule tag verification.


4. Pre-Commit Hooks

Pre-commit hooks are OPTIONAL. When used, they MUST be fast and local.

Local hooks MAY include:

Terminal window
dotnet format --verify-no-changes
pnpm lint
pnpm type-check

Do not run containerized integration tests or Playwright in pre-commit hooks. Keep slower checks in CI.


4. Domain Documentation Validation

When the project has docs/domain/, run structural completeness checks before merge:

Terminal window
node scripts/validate-domain-docs.mjs

Copy the script from the standards repository (standards/scripts/validate-domain-docs.mjs) or symlink it in consumer projects. The script checks:

  • YAML frontmatter on Feature Specs and Use Case Docs
  • Presence of Use Case Test Specs for each operation doc
  • docs/domain/agent-index.json exists and parses as JSON
  • Warnings for invariant coverage gaps, state transition coverage, and write/read asymmetry

Warnings do not fail CI by default; errors (missing test specs, invalid frontmatter keys) fail CI. Projects MAY treat warnings as errors in release branches.

See docs/guides/agentic-domain-driven-design.md §12 for the full check catalog.


5. Acceptance Test Stages

When a project has {ProjectName}.AcceptanceTests:

StageScope
Every PRdotnet test on Architecture, Domain, Application, Integration smoke, and acceptance tests filtered to @critical
Domain/API PRsFull acceptance test project when docs/domain/**, Application/**, WebApi/**, Infrastructure/**, migrations, or OpenAPI changed
Release candidate / nightlyAll acceptance tests including @slow and @external-dependency

Filter Reqnroll scenarios by tag in CI, for example:

Terminal window
dotnet test apps/api/tests/{ProjectName}.AcceptanceTests \
--filter "Category=critical"

Projects SHOULD copy standards/scripts/validate-feature-files.ps1 and run it in CI when Reqnroll feature files exist. Tag rules: docs/conventions/backend/api-acceptance-tests.md section 5.