Skip to content

CI / CD

All pipelines live in .github/workflows. Deploys are triggered by pushes to environment branches; images are built once and promoted through environments.

Pipeline map

Workflow Trigger Purpose
ci.yml PRs + pushes to prod lint, typecheck, build, coverage tests
cd-dev.yml push to dev build immutable images, deploy dev
cd-staging.yml push to staging build + deploy staging
prod-release.yml release event build + deploy production
release-please.yml push to prod versioning + changelog (CHANGELOG.md)
backmerge.yml push to prod open/refresh prod → dev backmerge PR
reset-dev-db.yml manual reset + seed the dev database (via SSM)
security-scan.yml, scan-dockerfile.yml, update-trivy-cache.yml PR / schedule container & dependency scanning
codspeed.yml PR benchmarked unit tests
apply-pr-template.yml PR PR description template

CI (every PR)

flowchart LR
    PR["pull_request"] --> INSTALL["pnpm install (frozen lockfile)"]
    INSTALL --> GEN["prisma generate"]
    GEN --> CHECK["pnpm check (typecheck + lint)"]
    CHECK --> BUILD["pnpm build:ci"]
    BUILD --> TEST["pnpm test:coverage"]
    TEST --> COV["coverage report → PR"]

Node 24, pnpm 10, cached TS build info. Coverage is published to the PR via the vitest coverage action. Security scans run in parallel on PRs.

CD (environment branches)

cd-dev / cd-staging / prod-release share a shape:

  1. Check out + login to GHCR (images are stored in the container registry).
  2. Set up Docker Buildx; compute image metadata.
  3. Build application image and a separate migration image.
  4. Push immutable images.
  5. Run migrations (migration image) then roll out the application image.
flowchart LR
    PUSH["push dev/staging/prod"] --> META["image metadata"]
    META --> APPB["build app image"]
    META --> MIG["build migration image"]
    APPB & MIG --> REG["GHCR"]
    REG --> DEP["deploy: run migrations → rollout app"]

[skip-deploy] in the commit message builds images without deploying.

Database

  • Migrations deploy via the migration image before the app image (see database/migrations.md).
  • reset-dev-db.yml destroys and re-seeds the dev database from a workflow (SSM + AWS), intended for controlled development resets only.

Release automation

Release-please derives the version + CHANGELOG.md from Conventional Commits on prod (see release-process.md and development/git-workflow.md).