Skip to main content

Quality gates

Every change reaches main through a pull request, and a pull request can only merge when the automated checks pass. This page lists the checks, how to run them locally, and the steps from branch to merge.

Pull request flow​

  1. Branch from an up-to-date main. Direct pushes to main are blocked.
  2. Commit with the local hooks enabled (see below). Add a changelog fragment.
  3. Push and open a pull request against main.
  4. Wait for the required checks: CI Gate and GitLeaks Secret Scanning.
  5. Squash-merge. You can enable auto-merge, for example gh pr merge --auto --squash, and it merges when the checks go green.

Merging to main runs the gates once more before the change is released.

The gates​

The CI workflow (.github/workflows/ci.yml) runs on every pull request to main.

Quality Gates job (always runs):

GateCommand
Typecheck (API, web, worker)pnpm typecheck
Lintpnpm lint
Formattingpnpm format:check
FE/BE contract driftpnpm contracts:check
API unit testspnpm test:api:unit
Scheduling engine testspnpm -F @aetech/scheduling-engine run test
CI script testspnpm test:gate
Analytics emit sitespnpm check:analytics-emit-sites
Widget i18n catalog driftpnpm check:wp-i18n
WordPress plugin zip versionpnpm check:wp-zip

Database Tests job: starts a fresh test database, runs pnpm db:test:reset, then pnpm test:api:int and pnpm test:api:e2e. It is skipped when a pull request only touches documentation, OpenSpec files, CI config other than ci.yml, root scripts or dependency manifests.

CI Gate passes only when both jobs passed or were legitimately skipped. It is the check that branch protection requires.

Contract drift​

pnpm contracts:check runs pnpm contracts:regen and fails if apps/api/openapi.json or apps/web/lib/api/generated/openapi.d.ts changed. If it fails, run pnpm contracts:regen and commit both files. See Contracts.

Opt-in suites​

These workflows do not run on every pull request. Add the run-heavy-ci label to a pull request to run them, or start them by hand:

  • QA Tests (Playwright): the browser suite across all projects. See Testing.
  • Lighthouse CI and the performance gate.

Security scans (dependency scan, secret scan, Semgrep) run on pull requests, on pushes or on a schedule. Their results are in each run's job summary and artifacts. Code Scanning (the GitHub Security tab) is not available on this repository.

Run the gates locally​

The Git hooks (installed by pnpm install through Husky) run most gates for you:

HookRuns
pre-commitlint-staged (ESLint and Prettier on staged files), then a typecheck of the touched apps
pre-pushpnpm typecheck, pnpm lint, pnpm format:check, pnpm contracts:check and more

To run the checks by hand before you push:

pnpm typecheck
pnpm lint
pnpm format:check
pnpm test:api:unit

pnpm ci:local runs a similar sequence in one command; pnpm ci:local:quick skips the unit tests. Run pnpm test:api:int too when you change database code; it needs the test database from Testing.

lint-staged only formats the files you stage, but the pre-push hook checks the whole repository. If the push fails on formatting, run pnpm format:fix, commit and push again.

Changelog fragments​

Every change adds one new file under openspec/changelog.d/ instead of editing openspec/changelog.md. Two open pull requests then never conflict on the changelog.

  • Name the file YYYY-MM-DD-short-slug.md.

  • Its content is one changelog block:

    ## [2026-08-10] - fix: short summary of the change (#123)

    What changed and why.
  • pnpm changelog:assemble folds the pending fragments into openspec/changelog.md at release time.

See openspec/changelog.d/README.md for the details.