From c0e32939e7123fcaae9a8aead2e2139364c22815 Mon Sep 17 00:00:00 2001 From: Schalli Date: Thu, 25 Jun 2026 10:57:45 +0200 Subject: [PATCH] feat(06-03): add act_runner compose definition and CI/CD setup runbook - docker-compose.ci.yml with act_runner service (ephemeral mode, Docker socket mount) - docs/ci-cd-setup.md runbook covering Gitea remote, runner setup, secrets, security - Registration token referenced from environment, never hardcoded (T-06-08) --- docker-compose.ci.yml | 34 +++++++++ docs/ci-cd-setup.md | 169 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 docker-compose.ci.yml create mode 100644 docs/ci-cd-setup.md diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml new file mode 100644 index 0000000..92e65c3 --- /dev/null +++ b/docker-compose.ci.yml @@ -0,0 +1,34 @@ +# CI/CD Infrastructure - act_runner for Gitea Actions +# +# This compose file documents the act_runner setup pattern for Tessera CI/CD. +# The runner executes Gitea Actions workflow jobs inside Docker containers. +# +# Usage: +# docker compose -f docker-compose.ci.yml up -d +# +# Prerequisites: +# - Gitea instance running with Actions enabled +# - Runner registration token from Gitea (Admin/Repo -> Actions -> Runners) +# - Set GITEA_INSTANCE_URL and GITEA_RUNNER_REGISTRATION_TOKEN in .env or environment + +services: + act_runner: + image: gitea/act_runner:latest + container_name: tessera-runner + restart: unless-stopped + environment: + GITEA_INSTANCE_URL: ${GITEA_INSTANCE_URL:?GITEA_INSTANCE_URL must be set} + GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN:?Token must be set} + GITEA_RUNNER_NAME: tessera-runner + GITEA_RUNNER_LABELS: "ubuntu-latest:docker://node:24,ubuntu-22.04:docker://node:24,ubuntu-20.04:docker://node:24" + GITEA_RUNNER_EPHEMERAL: "1" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - runner_data:/data + # Security note: Docker socket mount grants the runner control over host + # containers. This is acceptable for internal-only CI where only Claude + # pushes (D-11). Ephemeral mode (GITEA_RUNNER_EPHEMERAL=1) revokes + # runner credentials after each job for additional security. + +volumes: + runner_data: diff --git a/docs/ci-cd-setup.md b/docs/ci-cd-setup.md new file mode 100644 index 0000000..c702b96 --- /dev/null +++ b/docs/ci-cd-setup.md @@ -0,0 +1,169 @@ +# Tessera CI/CD Setup + +Runbook fuer die Einrichtung der Gitea-basierten CI/CD-Pipeline. + +## Voraussetzungen + +- Docker und Docker Compose installiert +- Gitea-Instanz mit aktivierten Actions +- Zugriff auf die Gitea-Administrationsoberflaeche + +## 1. Gitea-Repository einrichten + +1. In Gitea ein neues Repository erstellen (z.B. `tessera-ctl`) +2. Das Repository als Git-Remote hinzufuegen: + +```bash +git remote add origin https:////tessera-ctl.git +``` + +3. In den Repository-Einstellungen unter **Settings > Actions** sicherstellen, + dass Actions aktiviert ist. + +## 2. act_runner registrieren + +Der act_runner fuehrt Gitea Actions Workflow-Jobs in Docker-Containern aus. + +### Runner-Token generieren + +1. In Gitea navigieren zu: **Repository > Settings > Actions > Runners** + (oder Admin-Panel > Actions > Runners fuer globale Runner) +2. **Create registration token** klicken +3. Token kopieren + +### Runner starten + +Die Umgebungsvariablen setzen (z.B. in `.env` im Projektverzeichnis oder +direkt in der Shell): + +```bash +export GITEA_INSTANCE_URL=https://git.vicolab.de +export GITEA_RUNNER_REGISTRATION_TOKEN= +``` + +Runner starten: + +```bash +docker compose -f docker-compose.ci.yml up -d +``` + +Runner-Status pruefen: + +```bash +docker compose -f docker-compose.ci.yml logs act_runner +``` + +Der Runner registriert sich automatisch bei Gitea und ist bereit, Jobs +auszufuehren. + +### Bestehender Runner + +Wenn bereits ein act_runner als separater Docker-Container laeuft (z.B. +`gitea-runner`), kann `docker-compose.ci.yml` als Dokumentation und Vorlage +fuer eine Neueinrichtung verwendet werden. Der bestehende Runner muss nicht +ersetzt werden. + +Bestehenden Runner pruefen: + +```bash +docker ps --filter name=gitea-runner +``` + +## 3. Erforderliche Konfiguration + +### Umgebungsvariablen + +| Variable | Beschreibung | Wo setzen | +|----------|-------------|-----------| +| `GITEA_INSTANCE_URL` | URL der Gitea-Instanz | `.env` oder Systemumgebung | +| `GITEA_RUNNER_REGISTRATION_TOKEN` | Runner-Registrierungstoken | `.env` oder Systemumgebung | + +### Gitea Secrets (fuer die CI-Pipeline) + +In Gitea unter **Repository > Settings > Actions > Secrets** koennen Secrets +fuer die Pipeline konfiguriert werden. Aktuell werden keine Secrets in der +Pipeline benoetigt, da Images lokal gebaut und deployed werden (kein Registry-Push). + +Falls kuenftig Deploy-Pfade oder Credentials benoetigt werden: + +1. In Gitea **Settings > Actions > Secrets** den Secret anlegen +2. In `.gitea/workflows/ci.yml` ueber `${{ secrets.SECRET_NAME }}` referenzieren + +**Wichtig:** Secrets niemals in Logs ausgeben oder in Workflow-Dateien +hardcoden. + +## 4. Pipeline-Ueberblick + +Die CI/CD-Pipeline (`.gitea/workflows/ci.yml`) wird bei jedem Push auf `main` +ausgefuehrt und besteht aus drei aufeinander aufbauenden Jobs: + +1. **quality** -- Lint (Biome) und TypeScript Type-Check +2. **test** -- Vitest Unit- und Integrationstests +3. **build-deploy** -- Docker Images bauen und Services neu starten + +Ablauf: `quality` -> `test` -> `build-deploy` (jeder Job nur bei Erfolg des +vorherigen). + +### Kein Registry-Push + +Images werden **lokal auf dem Server gebaut** und nicht in eine Registry +gepusht (D-13). Da der Runner und die Applikation auf demselben Server laufen, +baut die Pipeline die Images direkt mit `docker compose build` und startet die +Services mit `docker compose up -d` neu. + +Vorteile: +- Keine Registry-Infrastruktur noetig +- Schnellerer Deploy (kein Push/Pull ueber Netzwerk) +- Einfachere Konfiguration + +## 5. Sicherheitshinweise + +### Docker Socket + +Der act_runner mountet den Host-Docker-Socket (`/var/run/docker.sock`), um Jobs +in Docker-Containern ausfuehren zu koennen. Das bedeutet: + +- Der Runner hat Zugriff auf den Docker-Daemon des Hosts +- Er kann Container starten, stoppen und inspizieren + +**Risikobewertung:** Akzeptabel fuer interne CI, da: +- Nur Claude pusht manuell bei Meilensteinen (D-11) +- Kein externer Code wird ausgefuehrt +- Ephemeral Mode ist aktiviert (siehe unten) + +### Ephemeral Runner + +`GITEA_RUNNER_EPHEMERAL=1` sorgt dafuer, dass der Runner seine Credentials +nach jedem Job widerruft und sich neu registriert. Das verhindert: + +- Persistente Zugriffstokens im Runner-Container +- Kompromittierung ueber alte Job-Artefakte +- Seitliche Bewegung zwischen Jobs + +### Workflow-Dateien + +Workflow-Dateien in `.gitea/workflows/` werden direkt aus dem Repository +geladen. Da nur vertrauenswuerdiger Code gepusht wird (D-11, Claude als +einziger Committer), ist das Risiko einer manipulierten Pipeline minimal. + +## 6. Fehlerbehebung + +### Runner registriert sich nicht + +1. Pruefen ob `GITEA_INSTANCE_URL` korrekt und erreichbar ist +2. Token ggf. neu generieren (Token sind einmalig verwendbar bei Ephemeral Mode) +3. Runner-Logs pruefen: `docker compose -f docker-compose.ci.yml logs act_runner` + +### Pipeline startet nicht + +1. In Gitea pruefen ob Actions fuer das Repository aktiviert ist +2. Pruefen ob der Runner als "online" angezeigt wird (Gitea > Actions > Runners) +3. Sicherstellen dass die Workflow-Datei unter `.gitea/workflows/` liegt +4. YAML-Syntax validieren + +### Docker-Build schlaegt fehl + +1. Sicherstellen dass `docker-compose.yml` im Arbeitsverzeichnis des Runners + erreichbar ist +2. Docker Daemon Status pruefen: `docker info` +3. Disk Space pruefen: `df -h`