fix: Build-Erkennung an den gebauten Commit koppeln, Smoke-Server sauber beenden
Zwei Fehler im neuen Deploy-Weg, beide bei einem Testlauf gefunden. 1. Das Skript uebersprang den Build, wenn vorher von Hand git pull lief. Die Entscheidung haengte an HEAD vs. origin/main -- nach einem manuellen Pull sind beide gleich, also "Nothing to do", obwohl der vorhandene Build aus einem aelteren Commit stammte. Genau das ist beim Deploy von v1.120.0 passiert: gepullt wurde, gebaut nicht, ausgeliefert blieb 1.119.4. Massgeblich ist jetzt .next/BUILD_COMMIT. Mein Rat, vor dem Skript git pull auszufuehren, hat den Fall ueberhaupt erst ausgeloest -- das Skript pullt selbst. 2. Der Smoke-Test-Server ueberlebte das Beenden. ( ... ) & startet eine Subshell, $! ist deren PID; node lief als Waise weiter und hielt Port 3999 belegt. Jeder weitere Deploy waere daran gescheitert. exec ersetzt die Subshell, kill greift, kill -9 fasst nach, der ERR-Trap raeumt ebenfalls auf, und vorab wird geprueft ob der Port frei ist. Beide Szenarien getestet: alter Build wird erkannt und neu gebaut, gleicher Stand wird uebersprungen, Port bleibt frei. v1.120.1 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
162c56d0d3
commit
dcbcb77dba
17
CHANGELOG.md
17
CHANGELOG.md
@ -2,6 +2,23 @@
|
||||
|
||||
All notable changes to this project are documented in this file.
|
||||
|
||||
## [1.120.1] - 2026-09-07
|
||||
|
||||
### Fixed
|
||||
- **Das Skript übersprang den Build, wenn vorher von Hand `git pull` ausgeführt wurde.**
|
||||
Die Entscheidung hing an `HEAD` vs. `origin/main` — nach einem manuellen Pull sind beide
|
||||
gleich, und das Skript sah keinen Grund zu bauen, obwohl der vorhandene Build aus einem
|
||||
älteren Commit stammte. Es lieferte weiter den alten Stand aus und meldete dabei
|
||||
„Nothing to do". Massgeblich ist jetzt `.next/BUILD_COMMIT`: aus welchem Commit der
|
||||
vorhandene Build tatsächlich stammt.
|
||||
- **Der Smoke-Test-Server überlebte das Beenden.** `( … ) &` startet eine Subshell, `$!`
|
||||
ist deren PID — `node` darin lief als Waise weiter und hielt Port 3999 belegt, womit
|
||||
jeder weitere Deploy am Smoke-Test gescheitert wäre. Mit `exec` ersetzt `node` die
|
||||
Subshell, `kill` greift, und ein `kill -9` fasst nach. Zusätzlich prüft das Skript vorab,
|
||||
ob der Port frei ist, und der ERR-Trap beendet den Server ebenfalls.
|
||||
|
||||
Beide Fehler kamen bei einem Testlauf ans Licht, nicht in Produktion.
|
||||
|
||||
## [1.120.0] - 2026-09-07
|
||||
|
||||
### Changed
|
||||
|
||||
5
TODO.md
5
TODO.md
@ -293,6 +293,11 @@ Umgestellt auf `dataSources.query()`; die Suche filtert jetzt auf `data_source`
|
||||
- [x] Smoke-Test vor dem Umschalten — der neue Build muss einmal geantwortet haben
|
||||
- [x] Umschalten erst danach, alter Stand bleibt als `.next-previous` liegen
|
||||
- [x] Beide Fälle getestet: Fehlschlag lässt `.next` unangetastet, Erfolg schaltet sauber um
|
||||
- [x] Build-Erkennung an den gebauten Commit gekoppelt (`.next/BUILD_COMMIT`) statt an
|
||||
`HEAD` vs. `origin/main` — sonst überspringt das Skript den Build, wenn jemand vorher
|
||||
von Hand `git pull` ausführt
|
||||
- [x] Smoke-Test-Server wird zuverlässig beendet (`exec`, sonst überlebt `node` als Waise
|
||||
und blockiert Port 3999 für alle weiteren Deploys)
|
||||
|
||||
**Warum:** `next build` lief direkt auf `.next` — also auf dem Verzeichnis, aus dem die
|
||||
laufende App bedient wird. Scheiterte der Build, war nicht nur das Update weg, sondern die
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "my-weekly-todo-list",
|
||||
"version": "1.120.0",
|
||||
"version": "1.120.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "my-weekly-todo-list",
|
||||
"version": "1.120.0",
|
||||
"version": "1.120.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@auth/prisma-adapter": "^2.11.1",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "my-weekly-todo-list",
|
||||
"version": "1.120.0",
|
||||
"version": "1.120.1",
|
||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -37,7 +37,7 @@ main() {
|
||||
# Bei einem Abbruch den halbfertigen Build wegraeumen. Der Hinweis "die laufende App
|
||||
# bleibt unberuehrt" stimmt seit v1.120.0 tatsaechlich -- vorher wurde direkt auf .next
|
||||
# gebaut, ein Fehlschlag riss die laufende Instanz mit.
|
||||
trap 'log "!!! Update FAILED at line $LINENO (exit $?) — die laufende App bleibt unberuehrt"; rm -rf "${APP_DIR:-.}/.next-build"' ERR
|
||||
trap 'log "!!! Update FAILED at line $LINENO (exit $?) — die laufende App bleibt unberuehrt"; kill "${SMOKE_PID:-0}" 2>/dev/null || true; rm -rf "${APP_DIR:-.}/.next-build"' ERR
|
||||
|
||||
# Fail fast instead of hanging on a credential prompt when run without a terminal
|
||||
# (systemd has no tty). The host authenticates via a read-only SSH deploy key.
|
||||
@ -65,14 +65,23 @@ main() {
|
||||
LOCAL=$(git rev-parse HEAD)
|
||||
REMOTE=$(git rev-parse origin/main)
|
||||
|
||||
# Rebuild when the code moved, when there is no build to serve, or when asked to.
|
||||
# Gebaut wird, wenn der vorhandene Build nicht zum aktuellen Stand passt.
|
||||
#
|
||||
# Frueher wurde HEAD mit origin/main verglichen. Das ging schief, sobald jemand vor dem
|
||||
# Skript von Hand `git pull` ausfuehrte: Dann waren beide gleich, das Skript sah keinen
|
||||
# Grund zu bauen -- und lieferte weiter den alten Build aus, obwohl neuer Code dalag.
|
||||
# Massgeblich ist deshalb, aus welchem Commit der vorhandene Build stammt.
|
||||
local BUILT_COMMIT=""
|
||||
[ -f "$APP_DIR/.next/BUILD_COMMIT" ] && BUILT_COMMIT=$(cat "$APP_DIR/.next/BUILD_COMMIT")
|
||||
|
||||
local NEEDS_BUILD=0
|
||||
[ "$LOCAL" != "$REMOTE" ] && NEEDS_BUILD=1
|
||||
[ ! -f "$APP_DIR/.next/standalone/server.js" ] && NEEDS_BUILD=1
|
||||
[ "$BUILT_COMMIT" != "$REMOTE" ] && NEEDS_BUILD=1
|
||||
[ "$FORCE" = "--force" ] && NEEDS_BUILD=1
|
||||
|
||||
if [ "$NEEDS_BUILD" -eq 0 ]; then
|
||||
log "Already up to date and a build is in place. Nothing to do."
|
||||
log "Vorhandener Build stammt aus ${BUILT_COMMIT:0:7} und passt zum aktuellen Stand."
|
||||
log "=== Update finished (no changes) ==="
|
||||
return 0
|
||||
fi
|
||||
@ -139,7 +148,20 @@ main() {
|
||||
# geht, muss er einmal wirklich geantwortet haben.
|
||||
log "--- Smoke-Test des neuen Builds ---"
|
||||
local SMOKE_PORT=3999
|
||||
( cd "$BUILD_DIR/standalone" && PORT=$SMOKE_PORT node server.js > /tmp/smoke-test.log 2>&1 ) &
|
||||
|
||||
# Steht noch ein Server aus einem abgebrochenen Lauf auf dem Port, wuerde der
|
||||
# Smoke-Test dessen Antwort messen statt der des neuen Builds.
|
||||
if (ss -ltn 2>/dev/null || netstat -ltn 2>/dev/null) | grep -q ":$SMOKE_PORT "; then
|
||||
log "!!! Port $SMOKE_PORT ist belegt -- vermutlich ein Rest aus einem abgebrochenen Lauf."
|
||||
log " Bitte pruefen: ss -ltnp | grep $SMOKE_PORT"
|
||||
rm -rf "$BUILD_DIR"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# exec ist hier wesentlich: Ohne das ersetzt node die Subshell NICHT, $! zeigt auf die
|
||||
# Subshell, und der node-Prozess ueberlebt das spaetere kill als Waise -- Port 3999
|
||||
# bliebe belegt und jeder weitere Deploy scheiterte daran.
|
||||
( cd "$BUILD_DIR/standalone" && exec env PORT=$SMOKE_PORT node server.js > /tmp/smoke-test.log 2>&1 ) &
|
||||
local SMOKE_PID=$!
|
||||
local SMOKE_OK=0
|
||||
for _ in $(seq 1 20); do
|
||||
@ -151,6 +173,11 @@ main() {
|
||||
done
|
||||
kill "$SMOKE_PID" 2>/dev/null || true
|
||||
wait "$SMOKE_PID" 2>/dev/null || true
|
||||
# Nachfassen, falls der Prozess das TERM ignoriert hat.
|
||||
if kill -0 "$SMOKE_PID" 2>/dev/null; then
|
||||
sleep 2
|
||||
kill -9 "$SMOKE_PID" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [ "$SMOKE_OK" -ne 1 ]; then
|
||||
log "!!! Smoke-Test fehlgeschlagen -- der neue Build antwortet nicht."
|
||||
@ -175,6 +202,9 @@ main() {
|
||||
fi
|
||||
mv "$BUILD_DIR" .next
|
||||
|
||||
# Damit der naechste Lauf erkennt, ob der Build noch zum Code passt.
|
||||
git rev-parse HEAD > .next/BUILD_COMMIT
|
||||
|
||||
# At boot this script runs before pm2-root.service, so the PM2 daemon is not up yet and
|
||||
# there is nothing to restart — pm2-root.service resurrects the app right after. Probing
|
||||
# with `pm2 describe` would be wrong here: any pm2 command spawns a daemon, and a stray
|
||||
|
||||
Loading…
Reference in New Issue
Block a user