feat: Phase 0 – Gerüst (FastAPI+SQLite, Multi-User-Login, React-App-Shell, Deploy)
Grundgerüst für Certain Finance: - Backend: FastAPI + SQLAlchemy + SQLite, Alembic-Migrationen (Batch-Mode), argon2-Passwort-Hashing, server-seitige Sitzungen im Cookie, Erst-Admin, Benutzerverwaltung mit Temporär-Passwort, Einstellungen je Benutzer. - Ein Prozess, ein Port: uvicorn liefert API (/api) und gebautes SPA aus, inkl. SPA-Deeplink-Fallback. - Frontend: React 18 + Vite + JSX, Design-Tokens (Light/Dark), i18n DE/EN, Inline-SVG-Icons (keine Emojis), Login, Passwort-ändern, Dashboard-Platzhalter, Benutzer- und Einstellungsseiten. - Deploy: nativer LXC-Installer + Update-Skript (systemd), env-Vorlage, Doku. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Executable
+103
@@ -0,0 +1,103 @@
|
||||
#!/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) ------------------------------------
|
||||
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
|
||||
Reference in New Issue
Block a user