CI/CD
The jobs that run on a pull request, when each one runs, and how to add one.
The jobs
Every pull request runs .github/workflows/ci.yml on GitHub Actions:
| Job | What it checks |
|---|---|
| Lint, deps, format | oxlint, syncpack, Prettier, the client env allowlist, and generated files against their sources |
| Backend tests | The full Vitest suite |
| Storybook tests | Every play test in Chromium |
| Semgrep | The rule tests, then the scan |
| ZAP scan and signed-in CSP | The web app's CSP, signed out and signed in, then ZAP against a running stack |
| Accessibility and CSP | The accessibility sweep, and the CSP on every static page |
| Builds | The web app, marketing site, blog, and docs, then the secrets scan of their output |
A draft runs nothing. Detect changes skips on a draft, and every other job needs it. Marking the pull request ready runs everything.
When a job runs
The first job, Detect changes, lists the pull request's files and decides which checks they affect. Every other job reads its list and skips when it isn't there.
Each check has a pattern in the paths map at the top of ci.yml. A pattern includes the check's own files and every workspace it imports, so a shared-ui change reruns the web-app build. Root files — package.json, yarn.lock, the workflows — run everything. Markdown only counts for formatting.
A manual run from the Actions tab runs every check.
Add a check
- Add an area to the
pathsmap in the Detect changes job, with a pattern for every file it reads. - Add a step to an existing job, or a new job with
needs: changesand anif:on the area. - Use
./.github/actions/setupfor Node and dependencies. Passplaywright: "true"if it needs Chromium.
Put a new job in its own job when its failure means something different from its neighbors'. An accessibility failure isn't a broken build, so it has its own job.
Artifacts
Each build is uploaded for three days as <app>-pr-<number>, and older uploads from the same pull request are deleted. The accessibility and ZAP jobs upload their reports as a11y-report and zap-report.
CD
Nothing runs on merge yet. There's no deploy target, so there's nothing for a deploy job to do. Hosting is decided — see AWS.
Also not built:
- Desktop builds. A Tauri build needs Rust and system libraries, and would be its own workflow.
- Required checks. Branch protection isn't turned on, so a failing check doesn't block a merge.
Related
- CI/CD — what runs, and why only what changed.
- GitHub Actions — how the workflow is shaped.
- Testing — running the tests yourself.