CI/CD
The GitHub Actions workflows, the local pre-push gate, quality gates, and how CI checks are toggled per context.
CI is GitHub Actions in .github/workflows/.
The same gates run locally before every push via a Husky hook, so a red
push should never reach GitHub.
The local gate — run it before pushing
The .husky/pre-push hook runs the CI gates locally. Its first step,
pnpm ci:precheck, is a superset of the CI "Static Checks" job:
pnpm ci:precheck
# = pnpm lint · turbo run lint · check-types · format:check
# · check:boundaries · check:architecture · check:no-raw-getsession
# · check:doc-versions · fallowIt then runs the test suite and an affected build.
pnpm check-types alone is not enough — it misses the repo-wide oxlint (pnpm lint) that
Static Checks runs. "Ready to push" means ci:precheck is green. Never bypass the gate with
SKIP_PREPUSH=1, --no-verify, or -n; scope-skip only the env-bound steps with RUN_BUILD=0 /
RUN_TESTS=0.
The main CI workflow (ci.yml)
| Job | Local equivalent |
|---|---|
| Static Checks | pnpm ci:precheck (superset) |
| Tests + coverage | pnpm turbo run test:ci |
| Build | pnpm turbo run build --affected |
| SonarQube | pnpm sonar:scan (needs docker + JDK) |
| a11y / e2e | see e2e.yml and the a11y job |
For the closest parity to the GitHub runner, RUN_ACT=1 git push runs the real
static job through act.
Quality gates
- Coverage on New Code ≥ 80% — SonarQube measures the changed/added production lines in the PR diff. A new untested module sinks the gate even if the rest of the repo is well covered. Write tests in the same change.
- react-doctor at 0 errors — a separate workflow (
react-doctor.yml). It is not in the default pre-push, so runnpx react-doctor@latest . --blocking error -ybefore finishing any React change (or opt in withRUN_REACT_DOCTOR=1 git push). - fallow — dead-code and duplicate detection, part of
ci:precheck.
Configurable CI
Which checks run is configurable per context and persistent via
.github/ci-config.json:
- Three contexts —
pr,default_branch(push tomain), andrelease(release-please PRs) — each with a boolean per toggleable check (static,tests,a11y,build,sonar,e2e,react_doctor,market_web_e2e,market_web_quality). - Toggle via the Configure CI workflow (Actions → Configure CI → Run
workflow) or by editing the JSON. Every workflow reads the config from
main, not the PR head — so a PR can't disable its own checks.
The workflow catalogue
| Workflow | Purpose |
|---|---|
ci.yml | Static checks, tests + coverage, build, Sonar, a11y |
e2e.yml | Playwright end-to-end tests |
configure-ci.yml | Write per-context check toggles to main |
ci-checkbox-comment.yml / ci-checkbox-handler.yml | PR checkbox → re-run controls |
vercel-preview-deploy.yml | Vercel preview deploys for PRs |
deploy-portal.yml | Deploy apps/portal to Cloudflare Workers |
storybook-deploy.yml | Deploy the Storybook component library |
db-migrate.yml | Apply Drizzle migrations |
react-doctor.yml | React health gate (0 errors) |
security-audit.yml | Dependency / security audit |
dependency-update.yml | Automated dependency bumps |
release-please.yml | Release PRs + changelogs |
bundle-size.yml | Bundle-size budget check |
pr-standards.yml | PR title / description / conventional-commit checks |
i18n-sync.yml | Keep translations in sync |
maintenance.yml | Scheduled maintenance jobs |
gitnexus-analyze.yml / graphify.yml | Refresh code-intelligence indexes |
ak-quality-gate.yml | Aggregate quality gate |
market-web-coverage.yml / market-web-e2e.yml / market-web-quality-gate.yml | apps/market-web checks |
teliaplay-e2e.yml | E2E against prod teliaplay.se |
turbo-cache-purge.yml | Purge the remote Turbo cache |
When CI fails
Recognise known failures before diagnosing from scratch — most red checks in
this repo are already-understood flakes or pre-existing, unrelated-app reds.
Confirm scope against main (gh run list --workflow ci.yml --branch main)
before blaming your diff, fix the root cause at the source, and record any new
failure mode in an obsidian-vault/01 Fleeting/ note.
See local development for running the tests behind these gates.