Merge #10: Update-Skript erkennt den Container-Zustand, Merkposten ergaenzt
CI / pruefen (push) Canceled after 0s

This commit was merged in pull request #10.
This commit is contained in:
2026-09-01 22:13:49 +00:00
2 changed files with 87 additions and 4 deletions
+15
View File
@@ -96,6 +96,9 @@ Statistiken, Benachrichtigungen, REST-API, PWA. Oberflächensprache **Deutsch**.
- **Dev-Umgebung**: Postgres auf `localhost:5439` (`docker-compose.dev.yml`),
Dev-Server auf **Port 3011** (3000 und 3010 sind von anderen Projekten belegt).
- **Screenshots**: `node scripts/shot.mjs <url> <ziel.png> [w] [h] [theme]`.
Achtung: das Skript meldet sich **nicht** an — bei geschützten Seiten entsteht
kommentarlos ein Bild der Anmeldemaske. Für angemeldete Ansichten den
Login-Weg aus `scripts/screenshots.mjs` nachbauen.
- Next hängt selbst einen Block an diese Datei an — der bleibt drin.
## Fortschritt
@@ -119,6 +122,18 @@ Statistiken, Benachrichtigungen, REST-API, PWA. Oberflächensprache **Deutsch**.
das ASCII-Schlusszeichen beendet den String. In JSX-Text und Kommentaren ok.
- Heredocs im Bash-Tool sind bei langen TSX-Dateien unzuverlässig — dann das
Write-Werkzeug benutzen.
- **Klickwege niemals gegen `npm run dev` prüfen.** Unter headless Chromium
scheitert der HMR-Socket (`ERR_INVALID_HTTP_RESPONSE`), dadurch hydratisiert
**keine** Seite und kein Knopf reagiert — ohne Seitenfehler, ohne
fehlgeschlagene Anfrage, es passiert einfach nichts. Sieht aus wie ein Fehler
im eigenen Code, ist aber die Umgebung. Stattdessen
`npm run build` und `PORT=3012 npm start`, dann dagegen klicken.
Formulare täuschen zusätzlich: die Anmeldung funktioniert auch ohne
JavaScript, wirkt also intakt.
- Vor `npm start` prüfen, ob der Port noch von einem früheren Lauf belegt ist —
sonst startet der neue Server gar nicht und man testet den alten Bau.
- Testdaten nach Klickproben wieder herstellen: die Proben schreiben in die
geseedete Entwicklungsdatenbank.
<!-- BEGIN:nextjs-agent-rules -->
+72 -4
View File
@@ -39,6 +39,10 @@ Ablauf: Datenbank sichern → Änderungen holen → Image bauen → neu starten
warten, bis die Instanz wieder antwortet. Die Datenbankmigrationen spielt der
Container beim Start selbst ein.
Geprüft wird zuerst http://127.0.0.1:APP_PORT/api/health. Ist der Port gar
nicht auf dem Host veröffentlicht — üblich hinter einem Reverse Proxy —,
zählt stattdessen der Healthcheck des Containers.
Optionen:
--ohne-backup Keine Sicherung anlegen (nicht empfohlen)
--ohne-pull Nichts aus dem Repository holen, nur neu bauen und starten
@@ -196,31 +200,95 @@ gut "Container laufen."
schritt "Auf die Instanz warten"
info "Die Datenbankmigrationen spielt der Container beim Start selbst ein."
# Der Container meldet seinen Zustand selbst — der HEALTHCHECK im Image fragt
# /api/health von innen ab. Das ist der verlässlichere Weg: hinter einem
# Reverse Proxy ist der App-Port oft gar nicht auf dem Host veröffentlicht,
# und dann sagt ein fehlschlagendes curl nichts über die Instanz aus.
# Gibt immer 0 zurück: die Funktion läuft auch im Fehlerpfad, und unter
# `set -e` dürfte eine Auskunft über den Zustand nicht selbst das Skript
# abbrechen, bevor der Weg zurück ausgegeben wurde.
container_zustand() {
local id
id=$($COMPOSE ps -q app 2>/dev/null || true)
if [ -z "$id" ]; then
printf 'kein-container'
return 0
fi
# Ohne HEALTHCHECK im Image ist .State.Health leer — dann bleibt der
# Laufzustand (running/exited) als grobe Auskunft.
docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}ohne-healthcheck:{{.State.Status}}{{end}}' \
"$id" 2>/dev/null || printf 'unbekannt'
return 0
}
GESUND=0
UEBER_CONTAINER=0
for _ in $(seq 1 60); do
if curl -fsS "http://127.0.0.1:${PORT}/api/health" >/dev/null 2>&1; then
GESUND=1
break
fi
if [ "$(container_zustand)" = "healthy" ]; then
GESUND=1
UEBER_CONTAINER=1
break
fi
sleep 2
done
if [ "$GESUND" -eq 1 ]; then
ANTWORT=$(curl -fsS "http://127.0.0.1:${PORT}/api/health" 2>/dev/null || true)
gut "Flimmer antwortet auf Port ${PORT}."
leise "$ANTWORT"
if [ "$UEBER_CONTAINER" -eq 1 ]; then
gut "Der Container meldet sich gesund."
leise "Auf Port ${PORT} war nichts zu erreichen — das ist normal, wenn die App"
leise "nur über einen Reverse Proxy erreichbar ist und den Port nicht veröffentlicht."
else
ANTWORT=$(curl -fsS "http://127.0.0.1:${PORT}/api/health" 2>/dev/null || true)
gut "Flimmer antwortet auf Port ${PORT}."
leise "$ANTWORT"
fi
printf '\n%s✓ Fertig — Version %s%s\n' "$GUT" "$NEUE_VERSION" "$AUS"
if [ "$VORHER_VERSION" != "$NEUE_VERSION" ]; then
info "Was sich geändert hat, steht in CHANGELOG.md."
fi
[ -n "$SICHERUNG" ] && leise "Sicherung: $SICHERUNG"
if [ -n "$SICHERUNG" ]; then
leise "Sicherung: $SICHERUNG"
fi
exit 0
fi
# --- Fehlschlag: konkreter Weg zurück ----------------------------------------
printf '\n%s✗ Die Instanz antwortet nach zwei Minuten nicht.%s\n\n' "$FEHLER" "$AUS" >&2
# Der Container-Zustand grenzt ein, wo es klemmt — ohne ihn sähe ein nicht
# veröffentlichter Port genauso aus wie eine abgestürzte App.
ZUSTAND=$(container_zustand)
case "$ZUSTAND" in
kein-container)
info "Es läuft gar kein app-Container. Der Start ist offenbar fehlgeschlagen."
;;
starting)
info "Der Container startet noch. Möglicherweise dauern die Migrationen länger —"
info "sieh im Log nach und gib ihm etwas Zeit."
;;
unhealthy)
info "Der Container läuft, meldet sich aber als nicht gesund. Der Fehler liegt"
info "also in der Anwendung, nicht am Port."
;;
ohne-healthcheck:running)
info "Der Container läuft, das Image bringt aber keinen Healthcheck mit (ältere"
info "Fassung). Ob die App wirklich antwortet, verrät nur das Log."
;;
ohne-healthcheck:*)
info "Der Container ist nicht gelaufen: ${ZUSTAND#ohne-healthcheck:}"
;;
*)
info "Container-Zustand: ${ZUSTAND}"
;;
esac
printf '\n'
info "Log ansehen:"
printf ' %s logs --tail 50 app\n\n' "$COMPOSE"