# 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-` 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](/home/hartmut/Documents/Copilot/capakraken/.github/workflows/ci.yml) workflow remains the merge gate for: - architecture guardrails - typecheck - lint - unit tests - build - E2E ### 2. Automatic Image Release [release-image.yml](/home/hartmut/Documents/Copilot/capakraken/.github/workflows/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](/home/hartmut/Documents/Copilot/capakraken/Dockerfile.prod): - `ghcr.io//-app:sha-` - `ghcr.io//-migrator:sha-` ### 3. Staging Promotion [deploy-staging.yml](/home/hartmut/Documents/Copilot/capakraken/.github/workflows/deploy-staging.yml) copies the canonical deploy bundle to the staging host: - [docker-compose.prod.yml](/home/hartmut/Documents/Copilot/capakraken/docker-compose.prod.yml) - [tooling/deploy/deploy-compose.sh](/home/hartmut/Documents/Copilot/capakraken/tooling/deploy/deploy-compose.sh) - the rest of [tooling/deploy](/home/hartmut/Documents/Copilot/capakraken/tooling/deploy/README.md) 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](/home/hartmut/Documents/Copilot/capakraken/tooling/deploy/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](/home/hartmut/Documents/Copilot/capakraken/.github/workflows/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 `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: - [docker-compose.prod.yml](/home/hartmut/Documents/Copilot/capakraken/docker-compose.prod.yml) - `.env.production` - `deploy.env` `.env.production` holds long-lived runtime configuration and secrets. The example file is [tooling/deploy/.env.production.example](/home/hartmut/Documents/Copilot/capakraken/tooling/deploy/.env.production.example). `deploy.env` is short-lived deployment metadata. The example file is [tooling/deploy/deploy.env.example](/home/hartmut/Documents/Copilot/capakraken/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: ```bash 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-` 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](/home/hartmut/Documents/Copilot/capakraken/.github/workflows/release-image.yml) publish `sha-` images 3. deploy that tag to staging through [deploy-staging.yml](/home/hartmut/Documents/Copilot/capakraken/.github/workflows/deploy-staging.yml) 4. validate staging 5. promote the same tag through [deploy-prod.yml](/home/hartmut/Documents/Copilot/capakraken/.github/workflows/deploy-prod.yml) The important property is artifact identity: staging and production run the same image, not two separate builds.