update.sh bzw. update.ps1 holen den neuen Stand und bauen den Stack neu: - Bricht ab, wenn git, docker compose oder die .env fehlen. - Bricht ab, wenn es lokale Aenderungen gibt — ein "git pull" wuerde dort im Konflikt enden. - Holt den Stand mit "git merge --ff-only" und zeigt die neuen Commits. - Baut nur neu, wenn es tatsaechlich Aenderungen gab (--force erzwingt es). - Wartet, bis die Anwendung auf APP_PORT antwortet, und gibt bei Zeitablauf das Container-Protokoll aus, statt stillschweigend Erfolg zu melden. - Zeigt zum Schluss die Migrationszeilen aus dem Start und den Status. - --prune raeumt auf Wunsch verwaiste Images auf, die bei jedem Neubau zurueckbleiben. README um einen Abschnitt "Aktualisieren" ergaenzt.
153 lines
4.7 KiB
Bash
Executable File
153 lines
4.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# =============================================================================
|
|
# QR-Code-Generator aktualisieren
|
|
#
|
|
# ./update.sh neuen Stand holen und, falls es Änderungen gibt,
|
|
# den Stack neu bauen und starten
|
|
# ./update.sh --force auch ohne neue Commits neu bauen
|
|
# ./update.sh --prune danach verwaiste Docker-Images aufräumen
|
|
# ./update.sh --help diese Hilfe
|
|
# =============================================================================
|
|
set -eu
|
|
|
|
FORCE=0
|
|
PRUNE=0
|
|
|
|
usage() {
|
|
cat <<'HILFE'
|
|
QR-Code-Generator aktualisieren.
|
|
|
|
./update.sh neuen Stand holen und, falls es Änderungen gibt,
|
|
den Stack neu bauen und starten
|
|
./update.sh --force auch ohne neue Commits neu bauen
|
|
./update.sh --prune danach verwaiste Docker-Images aufräumen
|
|
./update.sh --help diese Hilfe
|
|
HILFE
|
|
}
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--force) FORCE=1 ;;
|
|
--prune) PRUNE=1 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*)
|
|
echo "Unbekannte Option: $1" >&2
|
|
echo "Aufruf: ./update.sh [--force] [--prune]" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Immer im Projektverzeichnis arbeiten, egal von wo das Skript gestartet wird.
|
|
cd "$(dirname "$0")"
|
|
|
|
info() { echo "→ $*"; }
|
|
ok() { echo "✓ $*"; }
|
|
fail() { echo "✗ $*" >&2; exit 1; }
|
|
|
|
# --- Voraussetzungen --------------------------------------------------------
|
|
|
|
command -v git >/dev/null 2>&1 || fail "git ist nicht installiert."
|
|
command -v docker >/dev/null 2>&1 || fail "docker ist nicht installiert."
|
|
docker compose version >/dev/null 2>&1 ||
|
|
fail "docker compose ist nicht verfügbar (Docker Compose v2 wird benötigt)."
|
|
|
|
[ -f .env ] || fail ".env fehlt. Anlegen mit: cp .env.example .env"
|
|
|
|
# Ein "git pull" auf einem verändertem Arbeitsverzeichnis endet im Konflikt.
|
|
if [ -n "$(git status --porcelain)" ]; then
|
|
echo "✗ Es gibt lokale Änderungen im Arbeitsverzeichnis:" >&2
|
|
git status --short >&2
|
|
echo "" >&2
|
|
fail "Bitte zuerst committen oder mit 'git stash' beiseitelegen."
|
|
fi
|
|
|
|
# --- Neuen Stand holen ------------------------------------------------------
|
|
|
|
BEFORE="$(git rev-parse HEAD)"
|
|
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
|
|
|
info "Hole neuen Stand von origin/$BRANCH …"
|
|
git fetch --quiet origin
|
|
# --ff-only: lieber abbrechen als eine Merge-Situation erzeugen, die auf einem
|
|
# Server niemand auflösen will.
|
|
git merge --ff-only "origin/$BRANCH" ||
|
|
fail "Der lokale Stand lässt sich nicht ohne Merge aktualisieren. Bitte von Hand prüfen."
|
|
|
|
AFTER="$(git rev-parse HEAD)"
|
|
|
|
if [ "$BEFORE" = "$AFTER" ]; then
|
|
ok "Bereits auf dem neuesten Stand ($(git rev-parse --short HEAD))."
|
|
else
|
|
ok "Aktualisiert: $(git rev-parse --short "$BEFORE") → $(git rev-parse --short "$AFTER")"
|
|
echo ""
|
|
git --no-pager log --oneline "$BEFORE..$AFTER"
|
|
echo ""
|
|
fi
|
|
|
|
# --- Stack neu bauen --------------------------------------------------------
|
|
|
|
RUNNING="$(docker compose ps --status running --quiet 2>/dev/null | wc -l | tr -d ' ')"
|
|
|
|
if [ "$BEFORE" = "$AFTER" ] && [ "$FORCE" -eq 0 ] && [ "$RUNNING" -gt 0 ]; then
|
|
ok "Der Stack läuft und es gibt nichts Neues — kein Neubau nötig."
|
|
echo " (Mit ./update.sh --force lässt sich ein Neubau erzwingen.)"
|
|
exit 0
|
|
fi
|
|
|
|
info "Baue und starte den Stack neu — das dauert einige Minuten …"
|
|
docker compose up -d --build
|
|
|
|
# --- Warten, bis die Anwendung antwortet ------------------------------------
|
|
|
|
# Nur die Ziffern behalten — so stören weder Anführungszeichen noch ein
|
|
# Wagenrücklauf aus einer unter Windows bearbeiteten .env.
|
|
APP_PORT="$(grep -m1 '^APP_PORT=' .env | cut -d= -f2 | tr -cd '0-9')"
|
|
[ -n "$APP_PORT" ] || APP_PORT=3000
|
|
|
|
probe() {
|
|
if command -v curl >/dev/null 2>&1; then
|
|
curl --silent --fail --max-time 5 --output /dev/null "http://localhost:$APP_PORT/"
|
|
elif command -v wget >/dev/null 2>&1; then
|
|
wget --quiet --timeout=5 --tries=1 --spider "http://localhost:$APP_PORT/"
|
|
else
|
|
return 0 # Kein Prüfwerkzeug vorhanden — dann eben ohne Prüfung.
|
|
fi
|
|
}
|
|
|
|
info "Warte darauf, dass die Anwendung antwortet …"
|
|
ATTEMPT=0
|
|
until probe; do
|
|
ATTEMPT=$((ATTEMPT + 1))
|
|
if [ "$ATTEMPT" -ge 60 ]; then
|
|
echo ""
|
|
docker compose logs --tail 40 app >&2
|
|
fail "Die Anwendung antwortet nach 2 Minuten nicht. Protokoll siehe oben."
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
ok "Die Anwendung antwortet auf http://localhost:$APP_PORT"
|
|
|
|
# --- Ergebnis ---------------------------------------------------------------
|
|
|
|
echo ""
|
|
info "Datenbankmigrationen beim Start:"
|
|
docker compose logs app 2>/dev/null |
|
|
grep -E "migration|Migration|pending" |
|
|
tail -n 5 |
|
|
sed 's/^/ /'
|
|
|
|
echo ""
|
|
docker compose ps
|
|
|
|
if [ "$PRUNE" -eq 1 ]; then
|
|
echo ""
|
|
info "Räume verwaiste Docker-Images auf …"
|
|
docker image prune --force
|
|
fi
|
|
|
|
echo ""
|
|
ok "Fertig — Version $(git rev-parse --short HEAD)"
|