#!/bin/bash # deploy.sh – Rebreak Deploy Script (backend/-Layout, post-cutover) # # Wird vom Webhook-Listener (scripts/deploy-webhook/server.mjs) aufgerufen. # Repo-Root: /srv/rebreak # Clone: git@github.com:RaynisDev/rebreak.git # Backend: /srv/rebreak/backend (standalone Nitro, package: rebreak-backend) # # Ablauf: # 1. Git pull (via Deploy-Key) # 2. pnpm install --frozen-lockfile (mit hoisted node-linker via .npmrc) # 3. cd backend && pnpm --filter rebreak-backend build (Prisma generate + Nitro build) # 4. .output → .output-staging (atomisch via tmp) # 5. pm2 restart rebreak-staging --update-env # 6. pm2 restart rebreak-imap-staging / rebreak-idle-staging (best-effort, falls vorhanden) # 7. pm2 restart dns-rebreak-staging / dns-rebreak (best-effort, falls vorhanden) # # Secrets: via Infisical (INFISICAL_CLIENT_ID/SECRET in /etc/environment) — NICHT hier, # sondern in start-staging.sh / ecosystem.config.js zur Laufzeit. set -euo pipefail REPO_ROOT="/srv/rebreak" APP_DIR="${REPO_ROOT}/backend" NODE_BIN="/root/.nvm/versions/node/v24.11.1/bin/node" PNPM_BIN="/root/.nvm/versions/node/v24.11.1/bin/pnpm" PM2_BIN="/root/.nvm/versions/node/v24.11.1/bin/pm2" log() { echo "[deploy] $(date '+%H:%M:%S') $*"; } log_err() { echo "[deploy:err] $(date '+%H:%M:%S') $*" >&2; } log "=== Rebreak Deploy gestartet (backend/-Layout) ===" # 0. Sicherstellen dass PATH stimmt export PATH="/root/.nvm/versions/node/v24.11.1/bin:$PATH" # 1. Git pull via Deploy-Key (SSH ist konfiguriert in /root/.ssh/config) log "Step 1: git pull..." cd "${REPO_ROOT}" git fetch origin main 2>&1 git reset --hard origin/main 2>&1 git clean -fd 2>&1 log "Git updated to $(git rev-parse --short HEAD)" # 2. pnpm install (workspace-root, .npmrc mit node-linker=hoisted ist im Repo) log "Step 2: pnpm install --frozen-lockfile..." cd "${REPO_ROOT}" CI=true "${PNPM_BIN}" install --frozen-lockfile 2>&1 || { log_err "frozen-lockfile fehlgeschlagen, fallback ohne frozen..." CI=true "${PNPM_BIN}" install --no-frozen-lockfile 2>&1 } log "pnpm install done" # 3. Build backend (Nitro standalone) — Prisma generate ist Teil des build-scripts log "Step 3: pnpm --filter rebreak-backend build..." cd "${APP_DIR}" # NODE_OPTIONS: max 1.5 GB für den Build-Prozess (4 GB RAM Server) NODE_OPTIONS="--max-old-space-size=1536" CI=true "${PNPM_BIN}" --filter rebreak-backend build 2>&1 log "Build done" # 4. Atomisches Deploy: .output → .output-staging (relativ zu backend/) log "Step 4: Atomisches Deploy .output → .output-staging..." cd "${APP_DIR}" if [ -d ".output" ]; then rm -rf .output-staging-new cp -r .output .output-staging-new rm -rf .output-staging mv .output-staging-new .output-staging log ".output-staging aktualisiert" else log_err "FEHLER: .output Verzeichnis nicht gefunden nach Build!" exit 1 fi # 5. pm2 restart rebreak-staging (--update-env zieht neue Infisical-secrets) log "Step 5: pm2 restart rebreak-staging..." "${PM2_BIN}" restart rebreak-staging --update-env 2>/dev/null || \ "${PM2_BIN}" start "${REPO_ROOT}/ecosystem.config.js" --only rebreak-staging log "rebreak-staging restarted" # 6. IMAP + DNS Services (optional – kein Fehler wenn nicht vorhanden, Mo's Scope) log "Step 6: Optional services restart..." "${PM2_BIN}" restart rebreak-imap-staging 2>/dev/null || true "${PM2_BIN}" restart rebreak-idle-staging 2>/dev/null || true "${PM2_BIN}" restart dns-rebreak-staging 2>/dev/null || \ "${PM2_BIN}" start "${REPO_ROOT}/ecosystem.config.js" --only dns-rebreak-staging 2>/dev/null || true "${PM2_BIN}" restart dns-rebreak 2>/dev/null || \ "${PM2_BIN}" start "${REPO_ROOT}/ecosystem.config.js" --only dns-rebreak 2>/dev/null || true # 7. pm2 save "${PM2_BIN}" save 2>/dev/null || true log "=== Deploy erfolgreich: $(git -C ${REPO_ROOT} rev-parse --short HEAD) ==="