# Auto-Deploy-Pipeline Ziel: **`git push` = neue Version automatisch live**, ohne manuellen Eingriff. ## Überblick ``` Code ändern → git push (Gitea) → ┬─ Webhook → Hermes-Receiver → SSH → Dokploy → Build + Deploy └─ Cron-Polling (alle 2 Min) → Dokploy → Build + Deploy ``` Es gibt **zwei unabhängige Trigger**, weil der Gitea-Webhook unzuverlässig ist (siehe [„Warum zwei Trigger?"](#warum-zwei-trigger)): | Mechanismus | Latenz | Zuverlässigkeit | |-------------|--------|-----------------| | Gitea-Webhook → Receiver | ~5 s | ⚠️ sporadisch | | Cron-Polling | ≤ 2 min | ✅ garantiert | --- ## Komponenten ### 1. Gitea-Webhook Per Gitea-API erstellt: ```bash curl -X POST "https://git.kgessner.de/api/v1/repos/LuiiCode/techno-todo/hooks" \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "gitea", "config": {"url": "http://192.168.0.80:8002/hook", "content_type": "json"}, "events": ["push"], "active": true }' ``` Zeigt auf den Webhook-Receiver auf dem Hermes-Server (`192.168.0.80:8002`). ### 2. Webhook-Receiver (Hermes) Datei: `/home/hermes/webhook-receiver.py` - Python-Stdlib-`http.server` (keine Dependencies) - Lauscht auf `0.0.0.0:8002` - Bei `X-Gitea-Event: push` auf `refs/heads/main` des Ziel-Repos: - startet **asynchron** (Thread) `ssh root@192.168.0.184 /opt/deploy-techno-todo.sh` - antwortet sofort mit `200` (Gitea wartet nicht auf den Deploy) - Loggt in `/home/hermes/webhook-receiver.log` ### 3. Deploy-Skript (Dokploy-Host) Datei: `/opt/deploy-techno-todo.sh` **Idempotent** — deployt nur, wenn es neue Commits gibt: ```bash #!/bin/bash set -euo pipefail REPO_DIR="/opt/repos/techno-todo" SERVICE_NAME="techno-todo-v2-mzs9mj" cd "$REPO_DIR" git fetch --all --prune >/dev/null 2>&1 LOCAL=$(git rev-parse HEAD) REMOTE=$(git rev-parse origin/main) [ "$LOCAL" = "$REMOTE" ] && { echo "UP-TO-DATE: $LOCAL"; exit 0; } git reset --hard origin/main COMMIT=$(git rev-parse --short HEAD) docker build -t "techno-todo:${COMMIT}" . docker tag "techno-todo:${COMMIT}" techno-todo:latest docker service update --force --image "techno-todo:${COMMIT}" "$SERVICE_NAME" echo "DONE: deployed ${COMMIT}" ``` Das Repo liegt persistent unter `/opt/repos/techno-todo` auf dem Dokploy-Host. ### 4. Cron-Polling (Fallback) Auf dem Dokploy-Host: ```bash */2 * * * * /opt/deploy-techno-todo.sh >> /var/log/techno-todo-deploy.log 2>&1 ``` Da das Skript idempotent ist, passiert bei „keine neuen Commits" nichts (exit 0). --- ## Warum zwei Trigger? Der Gitea-Webhook erwies sich beim POC als **unzuverlässig**: Von mehreren Pushes wurden nur einige ausgelöst, andere gingen verloren. **Root-Cause:** Gitea läuft in einem **Kubernetes-Cluster (Talos)** auf Proxmox — also in einem anderen Netzwerk-Kontext als der Dokploy-Docker-Swarm-Host (`192.168.0.184`) und der Hermes-Server (`192.168.0.80`). Ausgehende Verbindungen aus dem K8s-Cluster zu internen `192.168.0.x`-Adressen sind nicht zuverlässig möglich (CNI/NAT-Isolation). Der Cron-Polling-Fallback umgeht das komplett: Er läuft direkt **auf** dem Dokploy-Host und holt sich den Git-Stand aktiv ab, statt auf einen eingehenden Webhook zu warten. --- ## Setup-Reihenfolge (für eine neue App) 1. Repo persistent auf Dokploy klonen: `/opt/repos/` 2. Deploy-Skript anpassen (Repo-Dir + Service-Name) → `/opt/deploy-.sh` 3. Cron-Job auf Dokploy einrichten (alle 2 Min) 4. (Optional) Webhook-Receiver auf Hermes starten + Gitea-Webhook einrichten ## Verifikation ```bash # 1. Push machen git push # 2. Nach ~2 Min prüfen: ssh root@192.168.0.184 "docker service ls --format '{{.Name}} {{.Image}}' | grep techno" # → techno-todo-v2-mzs9mj techno-todo: # 3. Live testen: curl -H "Host: techno-todo.192.168.0.184.sslip.io" http://192.168.0.184/ ```