Files
CapaKraken/docs/cicd-target-architecture.md

5.0 KiB

CI/CD Target Architecture

Goal

This document describes the canonical release path for CapaKraken.

The release model is now:

  1. PRs are validated by CI before merge.
  2. Every push to main publishes immutable app and migrator images.
  3. Staging and production promote the exact same sha-<commit> tag.
  4. The host deploys only from images and runtime env files.
  5. A deployment is successful only after GET /api/ready passes.

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:

  1. loads .env.production and deploy.env
  2. validates the rendered compose file
  3. pulls the immutable app and migrator images
  4. starts PostgreSQL and Redis
  5. runs Prisma migrations through the dedicated migrator image
  6. starts the new app container
  7. 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
  • separate staging and production hosts
  • GitHub Environments for staging and production
  • required approval for the production environment
  • monitoring on /api/health and /api/ready
  • PostgreSQL backup and restore drills

Runtime Configuration

The canonical host-side inputs are:

.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=redis should 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:

  1. choose the previous healthy sha-<commit> tag
  2. redeploy staging or production with that tag
  3. confirm GET /api/ready

This assumes schema changes follow backwards-compatible expand-and-contract rollout rules.

Production Update Summary

The standard production update is:

  1. merge to main after CI is green
  2. let release-image.yml publish sha-<commit> images
  3. deploy that tag to staging through deploy-staging.yml
  4. validate staging
  5. 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.