From 6bfba384d8915563b9a8caad523fd42af6bbb9b9 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Sat, 6 Jun 2026 02:11:21 -0300 Subject: [PATCH] fix(ci): deploy-vps recreates PM2 via bin + gates on /login 200 (#3270) Synchronized deploy-vps hardening (PM2 recreate via bin + /api/monitoring/health gate + fail-on-unhealthy). Supersedes #3262. Integrated into release/v3.8.12. --- .github/workflows/deploy-vps.yml | 53 ++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deploy-vps.yml b/.github/workflows/deploy-vps.yml index e1f572202c..760a53ba1e 100644 --- a/.github/workflows/deploy-vps.yml +++ b/.github/workflows/deploy-vps.yml @@ -19,25 +19,54 @@ jobs: steps: - name: Deploy via SSH uses: appleboy/ssh-action@v1 - continue-on-error: true with: host: ${{ secrets.VPS_HOST }} username: ${{ secrets.VPS_USER }} key: ${{ secrets.VPS_SSH_KEY }} port: 22 - timeout: 30s - command_timeout: 5m + timeout: 60s + command_timeout: 15m script: | - echo "=== Updating OmniRoute ===" - npm install -g omniroute@latest 2>&1 - INSTALLED_VERSION=$(omniroute --version 2>/dev/null || echo "unknown") - echo "Installed version: $INSTALLED_VERSION" + set -euo pipefail - echo "=== Restarting PM2 ===" - pm2 restart omniroute || pm2 start omniroute --name omniroute -- --port 20128 + echo "=== Updating OmniRoute ===" + npm install -g omniroute@latest + INSTALLED_VERSION=$(omniroute --version 2>/dev/null | tr -d '[:space:]' || echo "unknown") + echo "Installed CLI version: $INSTALLED_VERSION" + + # Recreate the PM2 process instead of `pm2 restart`. A bare restart + # re-runs whatever script path was saved earlier; after the build-output + # reorg (app/ -> dist/, .next -> .build/next) a process pinned to the old + # app/server-ws.mjs path can no longer start, and the node process dies + # while PM2 still reports "online" — so the box never binds :20128. + # Always launch via the `omniroute` bin so .env is loaded and the dist/ + # layout is resolved correctly. + echo "=== (Re)creating PM2 process via bin ===" + pm2 delete omniroute 2>/dev/null || true + pm2 start omniroute --name omniroute -- --port 20128 pm2 save - echo "=== Health Check ===" - sleep 3 - curl -sf http://localhost:20128/api/settings > /dev/null && echo "✅ OmniRoute is healthy" || echo "❌ Health check failed" + # Health gate: fail the deploy unless the box actually reports healthy. + # Poll /api/monitoring/health for "status":"healthy" (a deeper signal than + # a static page 200 — it confirms the app booted, not just that a port is + # bound). Boot can take a while after a native-module/build-layout change, + # so poll up to ~3min before giving up. + echo "=== Health Check (gates the deploy) ===" + ok=0 + for i in $(seq 1 36); do + BODY=$(curl -sf -m 5 http://localhost:20128/api/monitoring/health 2>/dev/null || true) + if printf '%s' "$BODY" | grep -q '"status":"healthy"'; then + ok=1 + echo "✅ /api/monitoring/health -> healthy (attempt $i) — version $INSTALLED_VERSION" + break + fi + echo "… not healthy yet (attempt $i/36), retrying in 5s" + sleep 5 + done + if [ "$ok" != "1" ]; then + echo "❌ Health check failed — /api/monitoring/health never reported healthy after ~3min" + echo "--- recent PM2 logs ---" + pm2 logs omniroute --lines 40 --nostream || true + exit 1 + fi echo "=== Deploy complete ==="