Files
breakpilot-compliance/docs-src/development/ci-cd-pipeline.md
Benjamin Admin 8742cb7f5a
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 35s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 41s
CI / test-python-dsms-gateway (push) Successful in 19s
docs: Qdrant und MinIO/Object-Storage Referenzen aktualisieren
- Qdrant: lokaler Container → qdrant-dev.breakpilot.ai (gehostet, API-Key)
- MinIO: bp-core-minio → Hetzner Object Storage (nbg1.your-objectstorage.com)
- CLAUDE.md, MkDocs, ARCHITECTURE.md, training.md, ci-cd-pipeline.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:18:29 +01:00

14 KiB

CI/CD Pipeline

Übersicht über den Deployment-Prozess für Breakpilot.

Übersicht

Komponente Build-Tool Deployment
Frontend (Next.js) Docker Mac Mini
Backend (FastAPI) Docker Mac Mini
Go Services Docker (Multi-stage) Mac Mini
Documentation MkDocs Docker (Nginx)

Deployment-Architektur

┌─────────────────────────────────────────────────────────────────┐
│                      Entwickler-MacBook                          │
│                                                                   │
│   breakpilot-pwa/                                                │
│   ├── studio-v2/          (Next.js Frontend)                    │
│   ├── admin-v2/           (Next.js Admin)                       │
│   ├── backend/            (Python FastAPI)                       │
│   ├── consent-service/    (Go Service)                          │
│   ├── klausur-service/    (Python FastAPI)                      │
│   ├── voice-service/      (Python FastAPI)                      │
│   ├── ai-compliance-sdk/  (Go Service)                          │
│   └── docs-src/           (MkDocs)                              │
│                                                                   │
│   $ ./sync-and-deploy.sh                                         │
└───────────────────────────────┬─────────────────────────────────┘
                                │
                                │ rsync + SSH
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                         Mac Mini Server                          │
│                                                                   │
│   Docker Compose                                                 │
│   ├── website (Port 3000)                                       │
│   ├── studio-v2 (Port 3001)                                     │
│   ├── admin-v2 (Port 3002)                                      │
│   ├── backend (Port 8000)                                       │
│   ├── consent-service (Port 8081)                               │
│   ├── klausur-service (Port 8086)                               │
│   ├── voice-service (Port 8082)                                 │
│   ├── ai-compliance-sdk (Port 8090)                             │
│   ├── docs (Port 8009)                                          │
│   ├── postgres                                                   │
│   ├── valkey (Redis)                                            │
│   ├── qdrant (extern: qdrant-dev.breakpilot.ai)                  │
│   └── object-storage (extern: nbg1.your-objectstorage.com)      │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

Sync & Deploy Workflow

1. Dateien synchronisieren

# Sync aller relevanten Verzeichnisse zum Mac Mini
rsync -avz --delete \
  --exclude 'node_modules' \
  --exclude '.next' \
  --exclude '.git' \
  --exclude '__pycache__' \
  --exclude 'venv' \
  --exclude '.pytest_cache' \
  /Users/benjaminadmin/Projekte/breakpilot-pwa/ \
  macmini:/Users/benjaminadmin/Projekte/breakpilot-pwa/

2. Container bauen

# Einzelnen Service bauen
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  build --no-cache <service-name>"

# Beispiele:
# studio-v2, admin-v2, website, backend, klausur-service, docs

3. Container deployen

# Container neu starten
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  up -d <service-name>"

4. Logs prüfen

# Container-Logs anzeigen
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  logs -f <service-name>"

Service-spezifische Deployments

Next.js Frontend (studio-v2, admin-v2, website)

# 1. Sync
rsync -avz --delete \
  --exclude 'node_modules' --exclude '.next' --exclude '.git' \
  /Users/benjaminadmin/Projekte/breakpilot-pwa/studio-v2/ \
  macmini:/Users/benjaminadmin/Projekte/breakpilot-pwa/studio-v2/

# 2. Build & Deploy
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  build --no-cache studio-v2 && \
  /usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  up -d studio-v2"

Python Services (backend, klausur-service, voice-service)

# Build mit requirements.txt
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  build klausur-service && \
  /usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  up -d klausur-service"
# Multi-stage Build (Go → Alpine)
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  build --no-cache consent-service && \
  /usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  up -d consent-service"

MkDocs Dokumentation

# Build & Deploy
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  build --no-cache docs && \
  /usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  up -d docs"

# Verfügbar unter: http://macmini:8009

Health Checks

Service-Status prüfen

# Alle Container-Status
ssh macmini "docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"

# Health-Endpoints prüfen
curl -s http://macmini:8000/health
curl -s http://macmini:8081/health
curl -s http://macmini:8086/health
curl -s http://macmini:8090/health

Logs analysieren

# Letzte 100 Zeilen
ssh macmini "docker logs --tail 100 breakpilot-pwa-backend-1"

# Live-Logs folgen
ssh macmini "docker logs -f breakpilot-pwa-backend-1"

Rollback

Container auf vorherige Version zurücksetzen

# 1. Aktuelles Image taggen
ssh macmini "docker tag breakpilot-pwa-backend:latest breakpilot-pwa-backend:backup"

# 2. Altes Image deployen
ssh macmini "/usr/local/bin/docker compose \
  -f /Users/benjaminadmin/Projekte/breakpilot-pwa/docker-compose.yml \
  up -d backend"

# 3. Bei Problemen: Backup wiederherstellen
ssh macmini "docker tag breakpilot-pwa-backend:backup breakpilot-pwa-backend:latest"

Troubleshooting

Container startet nicht

# 1. Logs prüfen
ssh macmini "docker logs breakpilot-pwa-<service>-1"

# 2. Container manuell starten für Debug-Output
ssh macmini "docker compose -f .../docker-compose.yml run --rm <service>"

# 3. In Container einloggen
ssh macmini "docker exec -it breakpilot-pwa-<service>-1 /bin/sh"

Port bereits belegt

# Port-Belegung prüfen
ssh macmini "lsof -i :8000"

# Container mit dem Port finden
ssh macmini "docker ps --filter publish=8000"

Build-Fehler

# Cache komplett leeren
ssh macmini "docker builder prune -a"

# Ohne Cache bauen
ssh macmini "docker compose build --no-cache <service>"

Monitoring

Resource-Nutzung

# CPU/Memory aller Container
ssh macmini "docker stats --no-stream"

# Disk-Nutzung
ssh macmini "docker system df"

Cleanup

# Ungenutzte Images/Container entfernen
ssh macmini "docker system prune -a --volumes"

# Nur dangling Images
ssh macmini "docker image prune"

Umgebungsvariablen

Umgebungsvariablen werden über .env Dateien und docker-compose.yml verwaltet:

# docker-compose.yml
services:
  backend:
    environment:
      - DATABASE_URL=postgresql://...
      - REDIS_URL=redis://valkey:6379
      - SECRET_KEY=${SECRET_KEY}

Wichtig: Sensible Werte niemals in Git committen. Stattdessen:

  • .env Datei auf dem Server pflegen
  • Secrets über HashiCorp Vault (siehe unten)

Woodpecker CI - Automatisierte OAuth Integration

Überblick

Die OAuth-Integration zwischen Woodpecker CI und Gitea ist vollständig automatisiert. Credentials werden in HashiCorp Vault gespeichert und bei Bedarf automatisch regeneriert.

!!! info "Warum automatisiert?" Diese Automatisierung ist eine DevSecOps Best Practice:

- **Infrastructure-as-Code**: Alles ist reproduzierbar
- **Disaster Recovery**: Verlorene Credentials können automatisch regeneriert werden
- **Security**: Secrets werden zentral in Vault verwaltet
- **Onboarding**: Neue Entwickler müssen nichts manuell konfigurieren

Architektur

┌─────────────────────────────────────────────────────────────────┐
│                        Mac Mini Server                           │
│                                                                   │
│   ┌───────────────┐         OAuth 2.0         ┌───────────────┐ │
│   │    Gitea      │ ←─────────────────────────→│  Woodpecker   │ │
│   │  (Port 3003)  │    Client ID + Secret     │  (Port 8090)  │ │
│   └───────────────┘                           └───────────────┘ │
│          │                                            │         │
│          │ OAuth App                                  │ Env Vars│
│          │ (DB: oauth2_application)                   │         │
│          │                                            │         │
│          ▼                                            ▼         │
│   ┌───────────────────────────────────────────────────────────┐ │
│   │                 HashiCorp Vault (Port 8200)                │ │
│   │                                                             │ │
│   │   secret/cicd/woodpecker:                                  │ │
│   │     - gitea_client_id                                      │ │
│   │     - gitea_client_secret                                  │ │
│   │                                                             │ │
│   │   secret/cicd/api-tokens:                                  │ │
│   │     - gitea_token (für API-Zugriff)                       │ │
│   │     - woodpecker_token (für Pipeline-Trigger)             │ │
│   └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

Credentials-Speicherorte

Ort Pfad Inhalt
HashiCorp Vault secret/cicd/woodpecker Client ID + Secret (Quelle der Wahrheit)
.env Datei WOODPECKER_GITEA_CLIENT/SECRET Für Docker Compose (aus Vault geladen)
Gitea PostgreSQL oauth2_application Tabelle OAuth App Registration (gehashtes Secret)

Troubleshooting: OAuth Fehler

Falls der Fehler "Client ID not registered" oder "user does not exist [uid: 0]" auftritt:

# Option 1: Automatisches Regenerieren (empfohlen)
./scripts/sync-woodpecker-credentials.sh --regenerate

# Option 2: Manuelles Vorgehen
# 1. Credentials aus Vault laden
vault kv get secret/cicd/woodpecker

# 2. .env aktualisieren
WOODPECKER_GITEA_CLIENT=<client_id>
WOODPECKER_GITEA_SECRET=<client_secret>

# 3. Zu Mac Mini synchronisieren
rsync .env macmini:~/Projekte/breakpilot-pwa/

# 4. Woodpecker neu starten
ssh macmini "cd ~/Projekte/breakpilot-pwa && \
  docker compose up -d --force-recreate woodpecker-server"

Das Sync-Script

Das Script scripts/sync-woodpecker-credentials.sh automatisiert den gesamten Prozess:

# Credentials aus Vault laden und .env aktualisieren
./scripts/sync-woodpecker-credentials.sh

# Neue Credentials generieren (OAuth App in Gitea + Vault + .env)
./scripts/sync-woodpecker-credentials.sh --regenerate

Was das Script macht:

  1. Liest die aktuellen Credentials aus Vault
  2. Aktualisiert die .env Datei automatisch
  3. Bei --regenerate:
    • Löscht alte OAuth Apps in Gitea
    • Erstellt neue OAuth App mit neuem Client ID/Secret
    • Speichert Credentials in Vault
    • Aktualisiert .env

Vault-Zugriff

# Vault Token (Development)
export VAULT_TOKEN=breakpilot-dev-token

# Credentials lesen
docker exec -e VAULT_TOKEN=$VAULT_TOKEN breakpilot-pwa-vault \
  vault kv get secret/cicd/woodpecker

# Credentials setzen
docker exec -e VAULT_TOKEN=$VAULT_TOKEN breakpilot-pwa-vault \
  vault kv put secret/cicd/woodpecker \
  gitea_client_id="..." \
  gitea_client_secret="..."

Services neustarten nach Credentials-Änderung

# Wichtig: --force-recreate um neue Env Vars zu laden
cd /Users/benjaminadmin/Projekte/breakpilot-pwa
docker compose up -d --force-recreate woodpecker-server

# Logs prüfen
docker logs breakpilot-pwa-woodpecker-server --tail 50