#!/usr/bin/env bash # ============================================================================= # Aktualisierung: laedt das aktuelle Release und ruft dessen install.sh auf. # Enthaelt selbst keinerlei Installationslogik. # # Eine einzelne Datei genuegt -- sie holt sich alles Weitere: # # curl -fsSLO https://gitea.int.eertmoed.net/alientim/tesm/raw/branch/main/deploy/update.sh # sudo bash update.sh tesm # # Auf einer bestehenden Installation liegt sie schon bereit: # # sudo bash /srv/tesm/deploy/update.sh tesm # ============================================================================= set -euo pipefail APP="${1:-}" TAG="${2:-latest}" # Alles nach dem Tag geht unveraendert an install.sh weiter. Ohne das liesse # sich eine benannte Instanz nicht aktualisieren: install.sh leitet den Namen # aus "--instance" ab, und ohne den Schalter entstuende neben "tesm-test" eine # zweite Installation namens "tesm" -- mit eigener Datenbank, eigener # nginx-Site und demselben Port. shift $(( $# > 2 ? 2 : $# )) EXTRA=("$@") [[ "$APP" == "tesm" || "$APP" == "tesm-license" ]] || { echo "Verwendung: update.sh [tag] [install.sh-Argumente ...]" >&2 echo "Beispiel : update.sh tesm latest --instance test" >&2 exit 2 } # --8<-- Bootstrap: Release holen -------------------------------------------- # Wortgleich in update.sh und upgrade.sh; ein Hygienetest vergleicht die beiden # Bloecke. Zwei eigenstaendige Skripte koennen sich keine Datei teilen, und # beide sollen als **einzelne Datei** genuegen: auf das Zielsystem legen, # ausfuehren, fertig -- auf einer 1.2.8 liegt nichts von diesem Projekt. # # Erwartet: $APP und $TAG. Setzt: $TAG (aufgeloest) und $SRC (entpacktes # Release). Raeumt sein Arbeitsverzeichnis beim Beenden auf. # # Zwei Fallen des Vorgaengers sind hier vermieden: # * Der Tag "latest" wird ueber die API aufgeloest, nie direkt in die # Download-URL geschrieben. Gitea liefert sonst mit HTTP 200 ein # automatisch erzeugtes Quell-Snapshot statt des echten Release-Anhangs. # * Nach dem Entpacken wird geprueft, dass ein install.sh existiert. BASE="${TESM_RELEASE_BASE:-https://gitea.int.eertmoed.net}" OWNER="${TESM_RELEASE_OWNER:-alientim}" # Ein Wagenruecklauf im Paket macht jedes Shell-Skript auf dem Ziel unbrauchbar # ("bad interpreter"). Die Pruefung darf dabei nicht selbst von einem # Zusatzpaket abhaengen: mit "file" -- das auf einem schlanken Server fehlt -- # endete sie in "command not found", grep bekam nichts zu sehen, und das Skript # machte weiter, als waere alles in Ordnung. hat_crlf() { local cr cr="$(printf '\r')" # -U (binaer lesen) ist unter Linux ohne Wirkung, auf einer # Windows-Buildmaschine aber entscheidend: dort entfernt grep den # Wagenruecklauf beim Lesen und findet deshalb nie einen. LC_ALL=C grep -qU "$cr" "$1" } BOOTSTRAP_WORK="" bootstrap_aufraeumen() { [[ -n "$BOOTSTRAP_WORK" ]] && rm -rf "$BOOTSTRAP_WORK"; } trap bootstrap_aufraeumen EXIT release_holen() { local repo="${TESM_RELEASE_REPO:-$APP}" asset for werkzeug in curl tar python3 find; do command -v "$werkzeug" >/dev/null 2>&1 || { echo "Auf diesem System fehlt $werkzeug -- ohne das geht es nicht." >&2 return 1 } done BOOTSTRAP_WORK="$(mktemp -d /tmp/tesm-release-XXXXXX)" if [[ "$TAG" == "latest" ]]; then echo "==> Ermittle aktuellen Release-Tag ..." TAG="$(curl -fsS "$BASE/api/v1/repos/$OWNER/$repo/releases/latest" \ | python3 -c 'import json,sys; print(json.load(sys.stdin)["tag_name"])')" || { echo "Kein Release gefunden unter $BASE/$OWNER/$repo." >&2 echo "Andere Quelle: TESM_RELEASE_BASE, TESM_RELEASE_OWNER, TESM_RELEASE_REPO." >&2 return 1 } echo " $TAG" fi asset="$repo-$TAG.tar.gz" echo "==> Lade $asset ..." curl -fsSL -o "$BOOTSTRAP_WORK/$asset" \ "$BASE/$OWNER/$repo/releases/download/$TAG/$asset" || { echo "Download fehlgeschlagen: $BASE/$OWNER/$repo/releases/download/$TAG/$asset" >&2 return 1 } echo "==> Entpacke ..." tar -xzf "$BOOTSTRAP_WORK/$asset" -C "$BOOTSTRAP_WORK" # Drei Ebenen, nicht zwei: release.sh packt mit dem Praefix "/", also # liegt das Skript unter /deploy/install.sh. Mit "-maxdepth 2" fand die # Suche nie etwas -- und die Fehlermeldung schob es auf den Download. SRC="$(find "$BOOTSTRAP_WORK" -maxdepth 3 -name install.sh -path '*/deploy/*' \ -printf '%h/..\n' | head -1)" [[ -n "$SRC" ]] || { echo "Im Paket fehlt deploy/install.sh -- Download unbrauchbar." >&2 return 1 } SRC="$(cd "$SRC" && pwd)" echo "==> Pruefe auf CRLF (Windows-Buildmaschinen) ..." if hat_crlf "$SRC/deploy/install.sh"; then echo "Das Paket enthaelt CRLF-Zeilenenden. Beim Paketieren fehlte" >&2 echo "'git -c core.autocrlf=false archive'." >&2 return 1 fi } # --8<-- Ende Bootstrap ------------------------------------------------------ release_holen read -r -p "Version $TAG fuer $APP${EXTRA[0]+ (${EXTRA[*]})} installieren? [j/N] " answer [[ "$answer" =~ ^[jJyY]$ ]] || exit 0 # Kein exec: sonst laeuft die Aufraeumfalle nie, und jedes Update liesse ein # entpacktes Release unter /tmp liegen. bash "$SRC/deploy/install.sh" --app "$APP" --yes ${EXTRA[0]+"${EXTRA[@]}"}