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 --quiet "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)"
|