`tr -dc … < /dev/urandom | head -c 6`: head schliesst die Pipe nach sechs Zeichen, tr bekommt SIGPIPE, und mit `set -o pipefail` gilt das als Fehlschlag. Das Skript endete mit 141, bevor es irgendetwas gebaut hatte — dieselbe Falle, vor der dreissig Zeilen weiter oben eine Anmerkung wegen `grep -q` steht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
149 lines
5.5 KiB
Bash
Executable File
149 lines
5.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Baut das Flaro-Image für beide Architekturen und legt es in die Registry.
|
|
#
|
|
# **Der Weg von Hand** — für den Fall, dass kein Gitea-Runner läuft. Sonst
|
|
# macht das `.gitea/workflows/image.yml` bei jedem Push von selbst.
|
|
#
|
|
# Tools/image-veroeffentlichen.sh → :latest
|
|
# Tools/image-veroeffentlichen.sh 0.2.0 → :latest und :0.2.0
|
|
#
|
|
# Nur eine Architektur — deutlich schneller, weil die fremde sonst unter
|
|
# Emulation läuft:
|
|
#
|
|
# FLARO_PLATTFORMEN=linux/amd64 Tools/image-veroeffentlichen.sh
|
|
#
|
|
# Vorher einmalig anmelden — das Passwort tippst du selbst ein:
|
|
#
|
|
# docker login git.scarriffle.com
|
|
|
|
set -euo pipefail
|
|
|
|
REGISTRY="${FLARO_REGISTRY:-git.scarriffle.com}"
|
|
PFAD="${FLARO_IMAGE_PATH:-scarriffle/flaro}"
|
|
BILD="$REGISTRY/$PFAD"
|
|
FASSUNG="${1:-}"
|
|
PLATTFORMEN="${FLARO_PLATTFORMEN:-linux/amd64,linux/arm64}"
|
|
|
|
cd "$(dirname "$0")/.."
|
|
|
|
command -v docker >/dev/null || { echo "docker fehlt."; exit 1; }
|
|
|
|
# **Ohne Anmeldung bricht der Push erst nach dem ganzen Bau ab.** Zwei
|
|
# Minuten Arbeit für eine Fehlermeldung, die am Anfang gestanden hätte.
|
|
# Kein `docker info | grep -q`: `grep -q` beendet die Pipe beim ersten
|
|
# Treffer, Docker bekommt SIGPIPE, und mit `set -o pipefail` gilt das als
|
|
# Fehlschlag. Die Prüfung meldete dann „Docker läuft nicht", während es lief.
|
|
if ! docker info >/dev/null 2>&1; then
|
|
echo "Docker läuft nicht."; exit 1
|
|
fi
|
|
if ! grep -q "$REGISTRY" ~/.docker/config.json 2>/dev/null; then
|
|
echo "Nicht an $REGISTRY angemeldet. Erst:"
|
|
echo
|
|
echo " docker login $REGISTRY"
|
|
exit 1
|
|
fi
|
|
|
|
# **Vor dem Bauen, nicht danach.** Laufen App und Browser farblich
|
|
# auseinander, soll das auffallen, bevor ein Image daraus wird.
|
|
if command -v python3 >/dev/null && [ -f Tools/tokens-pruefen.py ]; then
|
|
python3 Tools/tokens-pruefen.py || {
|
|
echo
|
|
echo "Abgebrochen. Mit FLARO_DRIFT_EGAL=1 trotzdem bauen."
|
|
[ "${FLARO_DRIFT_EGAL:-}" = "1" ] || exit 1
|
|
}
|
|
fi
|
|
|
|
# Fragt die Registry, welcher Stand dort unter `latest` liegt.
|
|
#
|
|
# Anonym — das Paket ist öffentlich lesbar. Schlägt es fehl, ist die Antwort
|
|
# leer, und der Aufrufer entscheidet, was das bedeutet.
|
|
registry_digest() {
|
|
local token
|
|
token=$(curl -fsS --max-time 20 \
|
|
"https://$REGISTRY/v2/token?scope=repository:$PFAD:pull&service=container_registry" \
|
|
| python3 -c 'import json,sys;print(json.load(sys.stdin).get("token",""))' 2>/dev/null) || return 1
|
|
[ -n "$token" ] || return 1
|
|
|
|
curl -fsS --max-time 20 -D- -o /dev/null \
|
|
-H "Authorization: Bearer $token" \
|
|
-H "Accept: application/vnd.oci.image.index.v1+json" \
|
|
"https://$REGISTRY/v2/$PFAD/manifests/latest" 2>/dev/null \
|
|
| awk 'BEGIN{IGNORECASE=1} /^docker-content-digest:/ {print $2}' | tr -d '\r'
|
|
}
|
|
|
|
MARKEN=(-t "$BILD:latest")
|
|
[ -n "$FASSUNG" ] && MARKEN+=(-t "$BILD:$FASSUNG")
|
|
|
|
# **Eine Kennung je Bau.**
|
|
#
|
|
# Sechs Zeichen, jedes Mal neu — auch bei unverändertem Quelltext. Sie landet
|
|
# im Abbild und steht danach in der Oberfläche unter „Einstellungen" sowie
|
|
# unter `/health`. Damit ist die Frage „läuft auf dem NAS wirklich der Bau von
|
|
# eben?" in zwei Sekunden beantwortet statt in einem halben Tag.
|
|
#
|
|
# Ohne I, O, 0 und 1: diese Kennung wird vorgelesen und abgetippt.
|
|
#
|
|
# **Nicht `tr < /dev/urandom | head -c 6`.** `head` schliesst die Pipe nach
|
|
# sechs Zeichen, `tr` bekommt SIGPIPE, und mit `set -o pipefail` gilt das als
|
|
# Fehlschlag — das Skript brach mit 141 ab, bevor es irgendetwas gebaut hatte.
|
|
# Dieselbe Falle wie oben bei `grep -q`, und sie hat hier zweimal zugeschlagen.
|
|
BUILD=$(python3 -c "import secrets; print(''.join(secrets.choice('ABCDEFGHJKLMNPQRSTUVWXYZ23456789') for _ in range(6)))")
|
|
echo "Build-Kennung dieses Laufs: $BUILD"
|
|
|
|
# **Ein eigener Builder.** Der Vorgabe-Builder von Docker Desktop kann kein
|
|
# Manifest mit zwei Architekturen bauen; `docker buildx create` schon.
|
|
docker buildx inspect flaro-bauer >/dev/null 2>&1 \
|
|
|| docker buildx create --name flaro-bauer --use >/dev/null
|
|
|
|
# **Den Digest festhalten, bevor gebaut wird.** Nur so lässt sich hinterher
|
|
# sagen, ob wirklich etwas Neues angekommen ist.
|
|
vorher=$(registry_digest || true)
|
|
|
|
echo "Baue $BILD für $PLATTFORMEN."
|
|
if ! docker buildx build \
|
|
--builder flaro-bauer \
|
|
--platform "$PLATTFORMEN" \
|
|
-f server/Dockerfile \
|
|
--build-arg "FLARO_BUILD=$BUILD" \
|
|
"${MARKEN[@]}" \
|
|
--push . ; then
|
|
echo
|
|
echo "Der Bau oder das Hochladen ist gescheitert. In der Registry liegt weiter:"
|
|
echo " ${vorher:-nichts}"
|
|
exit 1
|
|
fi
|
|
|
|
# **Nachsehen, statt zu glauben.**
|
|
#
|
|
# `docker buildx build --push` hat bei einem abgebrochenen Upload schon mit
|
|
# Rückgabewert 0 beendet, nachdem es „ERROR: failed to build" gedruckt hatte —
|
|
# ein TLS-Zeitlimit mitten im Hochladen. Das Skript meldete Erfolg, in der
|
|
# Registry lag das alte Image, und auf dem NAS kam eine Fassung an, die
|
|
# niemand gebaut hatte. Seitdem wird gefragt, nicht vertraut.
|
|
nachher=$(registry_digest || true)
|
|
|
|
if [ -z "$nachher" ]; then
|
|
echo
|
|
echo "Die Registry antwortet nicht auf $BILD:latest — hochgeladen wurde offenbar nichts."
|
|
exit 1
|
|
fi
|
|
|
|
if [ -n "$vorher" ] && [ "$vorher" = "$nachher" ]; then
|
|
echo
|
|
echo "In der Registry liegt noch derselbe Stand wie vorher:"
|
|
echo " $nachher"
|
|
echo "Das Hochladen ist also nicht durchgekommen. Noch einmal versuchen."
|
|
exit 1
|
|
fi
|
|
|
|
echo
|
|
echo "Fertig. In der Registry liegt jetzt:"
|
|
echo " $nachher"
|
|
echo
|
|
echo "Build-Kennung: $BUILD"
|
|
echo " Dieselbe muss nach dem Ziehen unter Einstellungen stehen."
|
|
echo " Steht dort eine andere, läuft auf dem NAS ein älteres Abbild."
|
|
echo
|
|
echo "Auf dem NAS:"
|
|
echo " image: $BILD:${FASSUNG:-latest}"
|