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?