#!/usr/bin/env bash # # Certain Finance – Update-Skript. # Holt den neuesten Stand aus Git, baut das Frontend neu, sichert die Datenbank # und startet den Dienst neu (der beim Start die Migrationen anwendet). # # Nutzung (als root im geklonten Repo): # ./deploy/update.sh Update holen, bauen, neu starten # ./deploy/update.sh --no-pull nur neu bauen (ohne git pull) # ./deploy/update.sh --no-build ohne Frontend-Neubau # set -euo pipefail APP_SLUG="certain-finance" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" ETC_DIR="/etc/$APP_SLUG" ENV_FILE="$ETC_DIR/env" DATA_DIR="/var/lib/$APP_SLUG" DO_PULL=1 DO_BUILD=1 for arg in "$@"; do case "$arg" in --no-pull) DO_PULL=0 ;; --no-build) DO_BUILD=0 ;; -h|--help) sed -n '2,12p' "${BASH_SOURCE[0]}"; exit 0 ;; *) echo "Unbekannte Option: $arg" >&2; exit 1 ;; esac done info() { printf '\033[0;32m==>\033[0m %s\n' "$*"; } warn() { printf '\033[0;33m[!]\033[0m %s\n' "$*"; } error() { printf '\033[0;31m[x]\033[0m %s\n' "$*" >&2; } if [[ "$(id -u)" -ne 0 ]]; then error "Bitte als root ausführen (z. B. 'sudo ./deploy/update.sh')." exit 1 fi if [[ ! -f "$ENV_FILE" ]]; then error "Keine Konfiguration in $ENV_FILE – bitte zuerst ./deploy/install.sh ausführen." exit 1 fi # --- Git-Update -------------------------------------------------------------- if [[ "$DO_PULL" -eq 1 ]]; then if [[ ! -d "$REPO_DIR/.git" ]]; then warn "$REPO_DIR ist kein Git-Repository – überspringe git pull." else info "Hole Updates aus Git …" before="$(git -C "$REPO_DIR" rev-parse --short HEAD 2>/dev/null || echo '?')" if ! git -C "$REPO_DIR" pull --ff-only; then error "git pull fehlgeschlagen (lokale Änderungen?)." echo " Stand ansehen: git -C \"$REPO_DIR\" status" exit 1 fi after="$(git -C "$REPO_DIR" rev-parse --short HEAD)" [[ "$before" == "$after" ]] && info "Bereits aktuell ($after)." || info "Aktualisiert: $before -> $after" fi fi # --- Datenbank sichern (vor der Migration) ---------------------------------- if [[ -f "$DATA_DIR/app.db" ]]; then mkdir -p "$DATA_DIR/backups" ts="$(date +%Y%m%d-%H%M%S)" cp "$DATA_DIR/app.db" "$DATA_DIR/backups/pre-update-$ts.db" info "Datenbank gesichert: backups/pre-update-$ts.db" fi # --- Python-Abhängigkeiten --------------------------------------------------- info "Aktualisiere Python-Abhängigkeiten …" "$REPO_DIR/backend/.venv/bin/pip" install -r "$REPO_DIR/backend/requirements.txt" >/dev/null # --- Frontend neu bauen ------------------------------------------------------ if [[ "$DO_BUILD" -eq 1 ]]; then info "Baue das Frontend neu …" ( cd "$REPO_DIR/web"; if [[ -f package-lock.json ]]; then npm ci; else npm install; fi; npm run build ) fi # --- Git-Commit in die Konfiguration schreiben (für /api/version) ----------- GIT_SHA="$(git -C "$REPO_DIR" rev-parse --short HEAD 2>/dev/null || echo '')" if grep -q '^APP_GIT_SHA=' "$ENV_FILE"; then sed -i "s|^APP_GIT_SHA=.*|APP_GIT_SHA=$GIT_SHA|" "$ENV_FILE" else echo "APP_GIT_SHA=$GIT_SHA" >> "$ENV_FILE" fi # --- Neu starten (wendet Migrationen an) ------------------------------------ if ! systemctl cat "$APP_SLUG" >/dev/null 2>&1; then error "Der systemd-Dienst '$APP_SLUG' existiert noch nicht." echo " Bitte einmalig die Ersteinrichtung ausführen:" echo " sudo $REPO_DIR/deploy/install.sh" exit 1 fi info "Starte Dienst neu …" systemctl restart "$APP_SLUG" PORT="$(grep -E '^APP_PORT=' "$ENV_FILE" | cut -d= -f2-)" PORT="${PORT:-8071}" ok=0 for _ in $(seq 1 30); do if curl -fsS "http://127.0.0.1:$PORT/api/health" >/dev/null 2>&1; then ok=1; break; fi sleep 2 done if [[ "$ok" -eq 1 ]]; then info "Update fertig – Dienst läuft." else warn "Backend antwortet noch nicht. Logs: journalctl -u $APP_SLUG -e" fi