feat(deploy): Migration-Detection in webhook-deploy.sh

Step 2.5 zwischen pnpm install und build:
- git diff vs .last-deployed-sha auf prisma/migrations + schema.prisma
- bei Änderungen: pnpm prisma migrate deploy via infisical run wrapper
  (idempotent, conservative — abort bei Fail vor pm2-restart)
- DATABASE_URL Fallback auf NUXT_DATABASE_URL analog start-staging.sh

Step 8: persistiert HEAD-SHA in .last-deployed-sha
.gitignore: .last-deployed-sha (server-only artifact)

Edge cases:
- First-deploy: .last-deployed-sha fehlt → run_migration=true (sicher dank
  Idempotenz)
- Infisical-Login-Fail: abort vor pm2-restart
- Migration-Fail: exit 1, alter Code läuft auf alter DB sauber

Old-trucko-Pattern (deploy.sh:58-65) macht migrate deploy unconditional;
rebreak-Variante macht es conditional → spart Infisical+DB-Roundtrip wenn
keine Migration-Files berührt wurden.
This commit is contained in:
chahinebrini 2026-05-07 19:09:12 +02:00
parent e76be7ee78
commit b38bf176b9
2 changed files with 72 additions and 0 deletions

3
.gitignore vendored
View File

@ -33,3 +33,6 @@ Thumbs.db
# xgit binary (generated)
xgit
# Server-only deploy state (NICHT committen — wird vom deploy.sh gepflegt)
.last-deployed-sha

View File

@ -51,6 +51,71 @@ CI=true "${PNPM_BIN}" install --frozen-lockfile 2>&1 || {
}
log "pnpm install done"
# 2.5 Prisma-Migration auto-deploy wenn neue migration-files committed wurden
# Detect via git diff zwischen .last-deployed-sha und HEAD.
# Idempotent: prisma migrate deploy skipped already-applied migrations.
# Failure-Mode: bei Migration-Fehler pm2 NICHT restarten (alter Code/alte DB konsistent).
# First-deploy-Edge-Case: wenn .last-deployed-sha fehlt → Migration ausführen (sicher
# weil idempotent).
log "Step 2.5: Migration-Check..."
PREV_SHA=$(cat "${REPO_ROOT}/.last-deployed-sha" 2>/dev/null || echo "")
CUR_SHA=$(git -C "${REPO_ROOT}" rev-parse HEAD)
run_migration=false
if [[ -z "$PREV_SHA" ]]; then
log "Kein .last-deployed-sha gefunden — first-deploy: Migration sicherheitshalber ausführen"
run_migration=true
elif ! git -C "${REPO_ROOT}" diff --quiet "$PREV_SHA"..HEAD -- backend/prisma/migrations/ backend/prisma/schema.prisma; then
log "Migration-Changes detected zwischen ${PREV_SHA} und ${CUR_SHA}"
run_migration=true
else
log "Keine Migration-Changes seit ${PREV_SHA} — skip migrate deploy"
fi
if $run_migration; then
log "Running prisma migrate deploy..."
cd "${APP_DIR}"
# Infisical-Wrapper für DATABASE_URL (analog start-staging.sh)
source /etc/environment
if [[ -z "${INFISICAL_CLIENT_ID:-}" || -z "${INFISICAL_CLIENT_SECRET:-}" ]]; then
log_err "INFISICAL_CLIENT_ID / INFISICAL_CLIENT_SECRET fehlt — kann Migration nicht ausführen"
exit 1
fi
INFISICAL_TOKEN=$(infisical login \
--method=universal-auth \
--client-id="${INFISICAL_CLIENT_ID}" \
--client-secret="${INFISICAL_CLIENT_SECRET}" \
--silent --plain 2>/dev/null)
if [[ -z "$INFISICAL_TOKEN" ]]; then
log_err "Infisical login fehlgeschlagen — Migration abgebrochen"
exit 1
fi
# DATABASE_URL injecten via infisical run; Aliasing analog start-staging.sh
# (Infisical-Secret heißt evtl. NUXT_DATABASE_URL, prisma erwartet DATABASE_URL).
infisical run \
--projectId="${INFISICAL_PROJECT_ID:-14b11b35-ef59-4b8a-a16b-398f0cc3ad93}" \
--env=staging \
--token="$INFISICAL_TOKEN" \
-- bash -c '
set -e
export DATABASE_URL="${DATABASE_URL:-${NUXT_DATABASE_URL:-}}"
if [[ -z "$DATABASE_URL" ]]; then
echo "[deploy:err] DATABASE_URL nicht in Infisical-staging — Migration abgebrochen" >&2
exit 1
fi
"'"${PNPM_BIN}"'" prisma migrate deploy --schema prisma/schema.prisma
' 2>&1 || {
log_err "Migration-Deploy fehlgeschlagen — pm2-restart ABGEBROCHEN (Daten-Konsistenz-Schutz)"
exit 1
}
log "Migration done"
fi
# 3. Build backend (Nitro standalone) — Prisma generate ist Teil des build-scripts
log "Step 3: pnpm --filter rebreak-backend build..."
cd "${APP_DIR}"
@ -90,4 +155,8 @@ log "Step 6: Optional services restart..."
# 7. pm2 save
"${PM2_BIN}" save 2>/dev/null || true
# 8. Last-deployed-SHA persistieren (für Step 2.5 beim nächsten Deploy)
echo "${CUR_SHA}" > "${REPO_ROOT}/.last-deployed-sha"
log "Last-deployed-SHA gespeichert: ${CUR_SHA}"
log "=== Deploy erfolgreich: $(git -C ${REPO_ROOT} rev-parse --short HEAD) ==="