Files
CapaKraken/docs/ci-cd-manual.md
T

7.4 KiB

CapaKraken CI/CD Manual

Overview

CapaKraken uses GitHub Actions for continuous integration and Docker for deployment. This document covers the full pipeline from code push to production.


1. CI Pipeline (Automatic on every PR)

What triggers it

Event Trigger
Pull request to main All CI jobs run
Push to main All CI jobs run

Jobs and their purpose

PR opened / pushed
    │
    ├──→ typecheck    (tsc --noEmit, ~40s)
    ├──→ lint         (ESLint via Turborepo, ~20s)
    ├──→ test         (Vitest unit tests, ~60s, needs PostgreSQL + Redis)
    │
    └──→ build        (next build, ~90s, runs after typecheck)
            │
            └──→ e2e  (Playwright, ~3-5min, runs after build)

typecheck, lint, and test run in parallel for speed. Build waits for typecheck. E2E waits for build.

What each job checks

Job Command What it catches
typecheck pnpm --filter @capakraken/web exec tsc --noEmit Type errors across the full web app
lint pnpm lint Code style violations, unused imports, etc.
test pnpm test:unit Unit test failures in engine, staffing, API, shared
build pnpm --filter @capakraken/web exec next build SSR errors, dynamic import issues, bundle problems
e2e pnpm test:e2e End-to-end user flow regressions

Required status checks

Before merging a PR, all 5 jobs must pass. Configure this in GitHub Settings > Branches > Branch protection rules > Require status checks.

Caching

The pipeline caches these artifacts to speed up subsequent runs:

Cache Key Saves
pnpm store pnpm-lock.yaml hash ~30s install time
Turborepo .turbo directory ~60s on unchanged packages
Playwright browsers Playwright version ~45s browser download

2. Local Development Quality Gates

Run these before pushing to catch issues early:

# Quick check (< 2 min)
pnpm --filter @capakraken/web exec tsc --noEmit && pnpm lint

# Full check (< 3 min)
pnpm test:unit

# Full check including build (< 5 min)
pnpm --filter @capakraken/web exec next build

Pre-commit hook (optional)

You can add a Git pre-commit hook to run the quick check automatically:

# .husky/pre-commit
pnpm --filter @capakraken/web exec tsc --noEmit
pnpm lint

3. Health Check Endpoints

Two endpoints are available for monitoring:

GET /api/health — Liveness Probe

Returns 200 if the Node.js process is running. No external dependencies checked.

{ "status": "ok", "timestamp": "2026-03-19T10:00:00.000Z" }

Use for: Kubernetes/Docker liveness probe, uptime monitoring.

GET /api/ready — Readiness Probe

Checks PostgreSQL and Redis connectivity. Returns 200 if all services are reachable, 503 if not.

// Healthy
{ "status": "ready", "postgres": "ok", "redis": "ok" }

// Unhealthy
{ "status": "not_ready", "postgres": "ok", "redis": "error" }

Use for: Kubernetes/Docker readiness probe, load balancer health checks, nginx upstream checks.


4. Production Docker Build

Building the production image

# Build the image
docker build -f Dockerfile.prod -t capakraken:latest .

# Test it locally
docker compose -f docker-compose.prod.yml up -d

Image details

Property Value
Base node:20-bookworm-slim
Size ~150-200 MB (vs ~1.5 GB dev image)
Output Next.js standalone mode
Healthcheck curl -f http://localhost:3000/api/health
Port 3000 (internal), mapped to 3100 externally

Environment variables

The production image requires these environment variables:

# Required
DATABASE_URL=postgresql://user:pass@host:5432/capakraken
REDIS_URL=redis://host:6379
NEXTAUTH_URL=https://capakraken.your-domain.com
NEXTAUTH_SECRET=<random-32-char-string>

# Optional
SENTRY_DSN=https://xxx@sentry.io/xxx
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=notifications@example.com
SMTP_PASSWORD=<password>
SMTP_FROM=CapaKraken <notifications@example.com>

Generate a secure NEXTAUTH_SECRET:

openssl rand -base64 32

5. Deployment

docker-compose (simplest)

# On your server
git pull
docker compose -f docker-compose.prod.yml up -d --build

# Run database migrations
docker compose -f docker-compose.prod.yml exec app \
  pnpm db:push

# Seed initial data (first deployment only)
docker compose -f docker-compose.prod.yml exec app \
  pnpm db:seed

Manual deployment (current setup)

Since capakraken.hartmut-noerenberg.com runs behind nginx:

# On the server
cd /home/hartmut/Documents/Copilot/capakraken
git pull origin main
pnpm install
pnpm db:generate
pnpm db:validate
pnpm --filter @capakraken/web exec next build
rm -rf apps/web/.next/cache  # clear stale cache

# Restart the app (systemd, pm2, or manual)
fuser -k 3100/tcp 2>/dev/null
PORT=3100 pnpm --filter @capakraken/web start &

nginx configuration

The existing nginx reverse proxy should forward to port 3100:

server {
    server_name capakraken.hartmut-noerenberg.com;

    location / {
        proxy_pass http://127.0.0.1:3100;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # SSE support (keep connection open)
        proxy_read_timeout 86400s;
        proxy_buffering off;
    }
}

6. Monitoring Setup

Sentry (error tracking)

After creating a Sentry project, add the DSN to .env.production:

SENTRY_DSN=https://xxx@sentry.io/xxx

Errors are automatically captured by the Sentry integration in Next.js.

Uptime monitoring

Point an external monitor (UptimeRobot, Better Stack, etc.) at:

https://capakraken.hartmut-noerenberg.com/api/health

Alert if status code != 200 for more than 2 consecutive checks.


7. Troubleshooting

CI job fails: "tsc --noEmit"

TypeScript error in the web app. Run locally:

pnpm --filter @capakraken/web exec tsc --noEmit

CI job fails: "test:unit"

Unit test failure. Run locally:

pnpm test:unit

CI job fails: "next build"

Build error (often ssr: false in Server Components, missing exports). Run locally:

pnpm --filter @capakraken/web exec next build

CI job fails: "e2e"

Playwright test failure. Check the HTML report artifact in the GitHub Actions run.

Production: 502 Bad Gateway

The Next.js process isn't running. Check:

ss -tlnp | grep 3100  # Is anything listening?
tail -50 /tmp/capakraken-dev.log  # Check app logs

Restart:

fuser -k 3100/tcp 2>/dev/null
pnpm dev &  # or pnpm start for production mode

Production: 500 Internal Server Error

Usually a stale Prisma client after schema changes:

pnpm db:generate
pnpm db:validate
rm -rf apps/web/.next
pnpm --filter @capakraken/web exec next build
# Restart the server

Database connection issues

Check the /api/ready endpoint:

curl -s https://capakraken.hartmut-noerenberg.com/api/ready | jq .

If postgres: "error", verify:

docker ps | grep postgres  # Is container running?
psql -h localhost -p 5433 -U capakraken -d capakraken  # Can you connect?