TeamVis Self-Host-Bundle v0.56.2
This commit is contained in:
1 parent
f53579d3a4
commit
6da3cc2283
11 files changed
+432
-30
No files matched your search
+64
-18
@@ -5,13 +5,21 @@
|
||||
# Aktualisiert eine bestehende Instanz in einem Rutsch:
|
||||
# 1. Pre-Update-Backup der Datenbank (Modus 2)
|
||||
# 2. `git pull` im Bundle → neue Migrationen + Skripte
|
||||
# 3. NUR die NEU hinzugekommenen Migrationen einspielen (git als Ledger:
|
||||
# welche Dateien seit dem letzten Stand dazukamen)
|
||||
# 3. Fehlende Migrationen einspielen — jede in EINER Transaktion zusammen
|
||||
# mit ihrem Eintrag in public.teamvis_schema_migrations (Modus 2)
|
||||
# 4. neues App-Image ziehen + Container neu starten
|
||||
#
|
||||
# Warum git als Ledger? Die Migrationen sind append-only. `git diff` zwischen
|
||||
# altem und neuem Stand liefert exakt die neuen Migrationsdateien — kein
|
||||
# separater DB-Tracker nötig, kein erneutes Ausführen alter Migrationen.
|
||||
# Warum ein Ledger in der DB? Früher diente `git diff OLD NEW` als Ledger.
|
||||
# Schlug dabei eine Migration fehl, war HEAD trotzdem schon vorgerückt — der
|
||||
# nächste Lauf meldete „keine neuen Migrationen", die restlichen fehlten
|
||||
# dauerhaft, und eine halb angewendete Migration blieb unbemerkt (Review
|
||||
# 04.10.2026). Jetzt gilt: eingespielt ist, was in der Tabelle steht; eine
|
||||
# fehlgeschlagene Migration rollt komplett zurück und wird beim nächsten
|
||||
# Lauf erneut versucht.
|
||||
#
|
||||
# Bestandsinstanzen ohne Tabelle: Beim ersten Lauf wird sie angelegt und mit
|
||||
# allen Migrationen des Stands VOR dem Pull befüllt — genau die galten nach
|
||||
# der alten Logik als eingespielt.
|
||||
#
|
||||
# Aufruf: bash deploy/selfhost/update.sh [instanz-verzeichnis]
|
||||
# (ohne Argument: das Instanz-Verzeichnis wird automatisch erkannt, wenn
|
||||
@@ -64,6 +72,9 @@ if [ "$MODE2" = "1" ]; then
|
||||
head "1) Datenbank-Backup"
|
||||
ts="$(date +%Y%m%d-%H%M%S)"
|
||||
dump="$INSTANCE/backup-db-$ts.sql"
|
||||
# Der Dump enthält alle Personendaten — nur für den Eigentümer lesbar
|
||||
# anlegen (vorher landete er mit 644 im Instanz-Verzeichnis).
|
||||
install -m 600 /dev/null "$dump"
|
||||
if ( cd "$INSTANCE" && docker compose exec -T -e PGPASSWORD="$PGPW" db pg_dump -U supabase_admin "$POSTGRES_DB" ) > "$dump" 2>/dev/null; then
|
||||
ok "Backup: $dump ($(wc -l < "$dump") Zeilen)"
|
||||
else
|
||||
@@ -84,21 +95,56 @@ else
|
||||
ok "Aktualisiert: ${OLD:0:8} → ${NEW:0:8}"
|
||||
fi
|
||||
|
||||
# ── 3. NUR neue Migrationen einspielen ────────────────────────────────
|
||||
head "3) Neue Migrationen"
|
||||
mapfile -t NEWMIG < <(git diff --diff-filter=A --name-only "$OLD" "$NEW" -- 'supabase/migrations/*.sql' 2>/dev/null | sort)
|
||||
if [ "${#NEWMIG[@]}" -eq 0 ]; then
|
||||
ok "Keine neuen Migrationen."
|
||||
elif [ "$MODE2" = "1" ]; then
|
||||
for m in "${NEWMIG[@]}"; do
|
||||
say "→ $m"
|
||||
dbsql < "$BUNDLE/$m"
|
||||
# ── 3. Fehlende Migrationen einspielen ────────────────────────────────
|
||||
head "3) Migrationen"
|
||||
if [ "$MODE2" = "1" ]; then
|
||||
LEDGER="public.teamvis_schema_migrations"
|
||||
if [ "$(dbsql -tAc "select to_regclass('$LEDGER') is not null")" != "t" ]; then
|
||||
say "Migrations-Ledger fehlt — wird angelegt und mit dem bisherigen Stand (${OLD:0:8}) befüllt."
|
||||
{
|
||||
echo "begin;"
|
||||
echo "create table $LEDGER (filename text primary key, applied_at timestamptz not null default now());"
|
||||
echo "revoke all on $LEDGER from anon, authenticated;"
|
||||
git ls-tree --name-only "$OLD" -- supabase/migrations/ | grep -E '\.sql$' | sort \
|
||||
| sed -E "s#^supabase/migrations/(.*)\$#insert into $LEDGER (filename) values ('\\1');#"
|
||||
echo "commit;"
|
||||
} | dbsql >/dev/null
|
||||
ok "Ledger angelegt ($(dbsql -tAc "select count(*) from $LEDGER") Einträge)."
|
||||
fi
|
||||
|
||||
mapfile -t APPLIED < <(dbsql -tAc "select filename from $LEDGER")
|
||||
declare -A DONE=()
|
||||
for f in "${APPLIED[@]}"; do [ -n "$f" ] && DONE["$f"]=1; done
|
||||
|
||||
PENDING=()
|
||||
for m in $(ls supabase/migrations/*.sql | sort); do
|
||||
[ -z "${DONE[$(basename "$m")]:-}" ] && PENDING+=("$m")
|
||||
done
|
||||
ok "${#NEWMIG[@]} Migration(en) eingespielt."
|
||||
|
||||
if [ "${#PENDING[@]}" -eq 0 ]; then
|
||||
ok "Keine offenen Migrationen."
|
||||
else
|
||||
for m in "${PENDING[@]}"; do
|
||||
name="$(basename "$m")"
|
||||
say "→ $name"
|
||||
# Migration + Ledger-Eintrag atomar: scheitert die Migration, bleibt
|
||||
# weder ein halber Schema-Stand noch ein Eintrag zurück.
|
||||
{ cat "$BUNDLE/$m"; printf "\ninsert into %s (filename) values ('%s');\n" "$LEDGER" "$name"; } \
|
||||
| dbsql --single-transaction >/dev/null \
|
||||
|| die "Migration $name fehlgeschlagen und vollständig zurückgerollt. Fehler beheben und update.sh erneut starten — bereits eingespielte Migrationen bleiben erhalten, die App wurde NICHT aktualisiert."
|
||||
done
|
||||
ok "${#PENDING[@]} Migration(en) eingespielt."
|
||||
fi
|
||||
else
|
||||
warn "Externe Supabase: bitte diese neuen Migrationen EINMAL in Supabase Studio (SQL-Editor) ausführen:"
|
||||
for m in "${NEWMIG[@]}"; do say " $BUNDLE/$m"; done
|
||||
read -r -p " Enter drücken, sobald sie eingespielt sind … " _ || true
|
||||
mapfile -t NEWMIG < <(git diff --diff-filter=A --name-only "$OLD" "$NEW" -- 'supabase/migrations/*.sql' 2>/dev/null | sort)
|
||||
if [ "${#NEWMIG[@]}" -eq 0 ]; then
|
||||
ok "Keine neuen Migrationen in diesem Update."
|
||||
else
|
||||
warn "Externe Supabase: bitte diese neuen Migrationen EINMAL in Supabase Studio (SQL-Editor) ausführen:"
|
||||
for m in "${NEWMIG[@]}"; do say " $BUNDLE/$m"; done
|
||||
warn "Schlägt eine fehl: nicht weitermachen, sondern Fehler beheben — update.sh zeigt sie beim nächsten Lauf NICHT erneut an."
|
||||
read -r -p " Enter drücken, sobald sie eingespielt sind … " _ || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── 4. Neues Image ziehen + Container neu starten ─────────────────────
|
||||
|
||||
Reference in new issue
Block a user