5.0 KiB
CI/CD Target Architecture
Goal
This document describes the canonical release path for CapaKraken.
The release model is now:
- PRs are validated by CI before merge.
- Every push to
mainpublishes immutableappandmigratorimages. - Staging and production promote the exact same
sha-<commit>tag. - The host deploys only from images and runtime env files.
- A deployment is successful only after
GET /api/readypasses.
Canonical Flow
1. Pull Request Validation
The main ci.yml workflow remains the merge gate for:
- architecture guardrails
- typecheck
- lint
- unit tests
- build
- E2E
2. Automatic Image Release
release-image.yml now runs automatically on every push to main and can still be started manually for rebuilds or tag overrides.
It publishes two images from Dockerfile.prod:
ghcr.io/<owner>/<repo>-app:sha-<commit>ghcr.io/<owner>/<repo>-migrator:sha-<commit>
3. Staging Promotion
deploy-staging.yml copies the canonical deploy bundle to the staging host:
GitHub Actions also writes a short-lived deploy.env containing APP_IMAGE, MIGRATOR_IMAGE, and the host port.
4. Host-Side Deployment
On the target host, deploy-compose.sh:
- loads
.env.productionanddeploy.env - validates the rendered compose file
- pulls the immutable
appandmigratorimages - starts PostgreSQL and Redis
- runs Prisma migrations through the dedicated
migratorimage - starts the new
appcontainer - waits for
GET /api/ready
The host does not build application code from Git anymore.
5. Production Promotion
deploy-prod.yml repeats the exact staging flow with the same image tag after staging acceptance.
That keeps staging and production on the same artifact instead of rebuilding.
Required Infrastructure
Minimum
- GitHub repository with Actions enabled
- GHCR or another container registry
- one Linux host with Docker Engine and Docker Compose v2
- PostgreSQL
- Redis
- SSH access from GitHub Actions to the host
- reverse proxy or load balancer in front of the app
Recommended
- separate staging and production hosts
- GitHub Environments for
stagingandproduction - required approval for the
productionenvironment - monitoring on
/api/healthand/api/ready - PostgreSQL backup and restore drills
Runtime Configuration
The canonical host-side inputs are:
- docker-compose.prod.yml
.env.productiondeploy.env
.env.production holds long-lived runtime configuration and secrets. The example file is tooling/deploy/.env.production.example.
deploy.env is short-lived deployment metadata. The example file is tooling/deploy/deploy.env.example.
Important invariants:
RATE_LIMIT_BACKEND=redisshould stay explicit in release environments- runtime AI, SMTP, and anonymization secrets belong to the host or platform secret layer
- admin settings are for verification and legacy-secret cleanup, not for secret rotation
Database Policy
Release environments must run migrations through the migrator image, which executes:
pnpm --filter @capakraken/db db:migrate:deploy
db:push remains a local-development tool, not a production rollout mechanism.
Rollback Model
Rollback is image-based:
- choose the previous healthy
sha-<commit>tag - redeploy staging or production with that tag
- confirm
GET /api/ready
This assumes schema changes follow backwards-compatible expand-and-contract rollout rules.
Production Update Summary
The standard production update is:
- merge to
mainafter CI is green - let release-image.yml publish
sha-<commit>images - deploy that tag to staging through deploy-staging.yml
- validate staging
- promote the same tag through deploy-prod.yml
The important property is artifact identity: staging and production run the same image, not two separate builds.