docker buildx build --push beendete mit Rückgabewert 0, nachdem es "ERROR: failed to build" gedruckt hatte — ein TLS-Zeitlimit mitten im Hochladen. Das Skript meldete "Fertig", in der Registry lag das alte Image, und auf dem NAS wäre eine Fassung angekommen, die niemand gebaut hat. Das ist die schlimmste Sorte Fehler: einer, der wie Erfolg aussieht. Jetzt wird der Digest vor und nach dem Bau abgefragt. Antwortet die Registry nicht, oder liegt dort noch derselbe Stand wie vorher, bricht das Skript mit Rückgabewert 1 ab und sagt es. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
128 lines
4.4 KiB
Bash
Executable File
128 lines
4.4 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")
|
|
|
|
# **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 \
|
|
"${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 "Auf dem NAS:"
|
|
echo " image: $BILD:${FASSUNG:-latest}"
|