#!/usr/bin/env bash # Deploy fuer Rippy — deployt den aktuellen 'main'-Stand auf die Ziel-VM. # Single Source of Truth ist 'main' (kein stable-Branch); die Ampel prueft nur, # befoerdert nichts. Vor dem Deploy selbst sicherstellen, dass die Ampel fuer den # zu deployenden Commit GRUEN ist. # # Generisch/portabel: Ziel-Host, Repo-URL und .env-Pfad kommen aus der Umgebung — # KEINE festen Adressen im Repo. Fuer eine Erst-Installation auf einem eigenen Host # reicht ohnehin der einfache Weg (siehe README): # git clone && cd rippy && cp .env.example .env (Werte eintragen) # docker compose up -d --build # # Dieses Skript ist nur die bequeme Remote-Variante: es SSHt zur VM, nutzt dort # einen EIGENEN Klon (Default ~/notfall-rippy) und fasst ein evtl. vorhandenes # Projektverzeichnis NIE an (git-Klon dort kollidiert mit dessen Sync). Die .env # gehoert der VM und wird nur GELESEN (fuer compose-Interpolation). # # Konfiguration ueber Umgebungsvariablen: # RIPPY_VM Ziel-Host fuer ssh, z.B. user@10.0.0.5 (PFLICHT) # RIPPY_REPO_URL Git-Repo-URL (branch main) (PFLICHT) # RIPPY_ENV_SRC Pfad zur .env auf der VM (Default: ~/rippy/.env) # RIPPY_CLONE Arbeits-Klon auf der VM (Default: ~/notfall-rippy) # Optionales Argument $1: nur einen Dienst neu bauen, z.B. ./deploy.sh api set -euo pipefail VM="${RIPPY_VM:?RIPPY_VM setzen, z.B. RIPPY_VM=user@10.0.0.5}" REPO_URL="${RIPPY_REPO_URL:?RIPPY_REPO_URL setzen (Git-URL des Rippy-Repos)}" ENV_SRC="${RIPPY_ENV_SRC:-}" # leer -> Remote-Default ~/rippy/.env CLONE="${RIPPY_CLONE:-}" # leer -> Remote-Default ~/notfall-rippy DIENST="${1:-}" ssh "$VM" bash -s -- "$REPO_URL" "$ENV_SRC" "$CLONE" "$DIENST" <<'REMOTE' set -euo pipefail REPO_URL="$1" ENV_SRC="${2:-$HOME/rippy/.env}" CLONE="${3:-$HOME/notfall-rippy}" # ⚠️ ${4:-}, nicht "$4" (Befund 26.07.2026): Leere Argumente ueberleben den Weg # durch ssh nicht — die Gegenseite bekommt die Befehlszeile als EINEN String und # parst sie neu, wobei "" ersatzlos verschwindet. Wer also ohne RIPPY_ENV_SRC, # RIPPY_CLONE und ohne Dienst-Argument deployte (der dokumentierte Normalfall!), # bekam von 'set -u' nur ein "line 5: $4: unbound variable" und kein Deploy. DIENST="${4:-}" # ⚠️ NICHT DEPLOYEN, WÄHREND EIN JOB LÄUFT (Vorfall 26.07.2026, selbst verursacht) # # `docker compose up -d --build` baut den worker-Container neu — und tötet damit # einen laufenden Rip. Genau das ist passiert: mitten in einem Blu-ray-Rip, bei # 12 %, nach 5,1 GB. Die Warnung stand im SAVEPOINT und half nichts, weil sie # niemand las und nichts sie prüfte. Jetzt prüft es das Skript. # # Übersteuern mit RIPPY_TROTZDEM=1 — dann ist es eine Entscheidung und kein # Versehen. if [ -z "${RIPPY_TROTZDEM:-}" ]; then ANTWORT="$(curl -s -m 5 http://localhost:8000/health/arbeit 2>/dev/null || true)" case "$ANTWORT" in *'"arbeit":true'*|*'"arbeit": true'*) echo "ABBRUCH: Auf dieser Maschine läuft gerade ein Job." >&2 echo " Ein Rebuild des worker-Containers würde ihn töten." >&2 echo "$ANTWORT" | tr ',' '\n' | grep -E '"(status|titel|progress)"' >&2 || true echo " Warten, oder bewusst überstimmen: RIPPY_TROTZDEM=1 ./deploy.sh" >&2 exit 1 ;; esac fi if [ ! -d "$CLONE/.git" ]; then git clone --branch main "$REPO_URL" "$CLONE" fi cd "$CLONE" git fetch origin main git reset --hard origin/main # ⚠️ Eine fehlende .env-Quelle war bisher eine geschluckte Warnung — und damit # eine Falle (Befund 26.07.2026). Auf der Ziel-VM lag die echte .env unter # ~/projects/rippy/.env, der Default zeigte auf ~/rippy/.env. Das `cp` schlug # also jedes Mal fehl, die Zeile scrollte im Build-Ausgabe-Rauschen vorbei, und # gebaut wurde mit der Kopie im Klon: zwei Tage alt, mit einem inzwischen toten # MAKEMKV_URL_BASE-Notbehelf und einem JWT_SECRET_KEY aus der Zeit vor dem # Auth-Rueckbau. Ergebnis: jeder worker-Build brach ab, und die Ursache stand # nirgends. if [ -f "$ENV_SRC" ]; then cp "$ENV_SRC" .env echo "OK: .env aus $ENV_SRC uebernommen." elif [ -f .env ]; then echo "WARNUNG: $ENV_SRC gibt es nicht — es gilt die .env IM KLON ($CLONE/.env)." >&2 echo " Stand dieser Datei: $(date -r .env '+%d.%m.%Y %H:%M')" >&2 echo " Ist das nicht gewollt: RIPPY_ENV_SRC= setzen." >&2 ls -1 "$HOME"/*/.env "$HOME"/*/*/.env 2>/dev/null | head -5 | sed 's/^/ Kandidat: /' >&2 || true else echo "ABBRUCH: Keine .env — weder unter $ENV_SRC noch im Klon." >&2 echo " Ohne sie baut compose mit leeren Werten (kein DB-Passwort," >&2 echo " keine API-Schluessel). RIPPY_ENV_SRC= setzen." >&2 exit 1 fi sed -i '/^RIPPY_VERSION=/d' .env echo "RIPPY_VERSION=$(git rev-parse --short HEAD)" >> .env docker compose -p rippy up -d --build $DIENST docker compose -p rippy ps --format 'table {{.Name}}\t{{.Status}}' REMOTE