fix(deploy): free PORT before PM2 start to clear EADDRINUSE orphans
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
749dc237f1
commit
540bce911f
1 file changed
+24
-4
@@ -381,16 +381,35 @@ jobs:
|
|||||||
|
|
||||||
# Next.js prefers an already-set process PORT over .env. PM2 may still
|
# Next.js prefers an already-set process PORT over .env. PM2 may still
|
||||||
# have PORT=3000 from an older start, while .env (and nginx) expect 3002.
|
# have PORT=3000 from an older start, while .env (and nginx) expect 3002.
|
||||||
# Export PORT before reload so --update-env aligns the running process.
|
# Export PORT before start so the process matches health checks.
|
||||||
DEPLOY_PORT="$(grep -E '^[[:space:]]*PORT=' "${LIVE}/.env" 2>/dev/null | tail -1 | cut -d= -f2- || true)"
|
DEPLOY_PORT="$(grep -E '^[[:space:]]*PORT=' "${LIVE}/.env" 2>/dev/null | tail -1 | cut -d= -f2- || true)"
|
||||||
DEPLOY_PORT="$(printf '%s' "${DEPLOY_PORT}" | tr -cd '0-9')"
|
DEPLOY_PORT="$(printf '%s' "${DEPLOY_PORT}" | tr -cd '0-9')"
|
||||||
DEPLOY_PORT="${DEPLOY_PORT:-3002}"
|
DEPLOY_PORT="${DEPLOY_PORT:-3002}"
|
||||||
export PORT="${DEPLOY_PORT}"
|
export PORT="${DEPLOY_PORT}"
|
||||||
echo "PM2/health PORT=${PORT}"
|
echo "PM2/health PORT=${PORT}"
|
||||||
|
|
||||||
echo "Starting PM2 (zero-downtime reload)..."
|
free_tcp_port() {
|
||||||
|
local port="$1"
|
||||||
|
[ -n "${port}" ] || return 0
|
||||||
|
if command -v fuser >/dev/null 2>&1; then
|
||||||
|
fuser -k "${port}/tcp" 2>/dev/null || true
|
||||||
|
elif command -v lsof >/dev/null 2>&1; then
|
||||||
|
# Portable fallback when fuser is unavailable.
|
||||||
|
lsof -tiTCP:"${port}" -sTCP:LISTEN 2>/dev/null | xargs -r kill -9 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Starting PM2 with a clean PORT=${PORT} listener..."
|
||||||
cd "${LIVE}"
|
cd "${LIVE}"
|
||||||
pm2 reload next --update-env || pm2 start pnpm --name next --update-env -- start
|
# Cutover already stopped the app, but failed deploys can leave orphans
|
||||||
|
# on 3002 (or an old PM2 env still bound to 3000).
|
||||||
|
pm2 stop next --kill-timeout 10000 2>/dev/null || true
|
||||||
|
free_tcp_port "${PORT}"
|
||||||
|
free_tcp_port 3000
|
||||||
|
sleep 1
|
||||||
|
pm2 delete next 2>/dev/null || true
|
||||||
|
PORT="${PORT}" pm2 start pnpm --name next -- start
|
||||||
|
pm2 save 2>/dev/null || true
|
||||||
|
|
||||||
sleep 3
|
sleep 3
|
||||||
if ! pm2 show next 2>/dev/null | grep -q 'online'; then
|
if ! pm2 show next 2>/dev/null | grep -q 'online'; then
|
||||||
@@ -415,7 +434,8 @@ jobs:
|
|||||||
if [ "${HEALTH_OK}" != "1" ]; then
|
if [ "${HEALTH_OK}" != "1" ]; then
|
||||||
echo "ERROR: Health check failed after deploy (${HEALTH_URL})" >&2
|
echo "ERROR: Health check failed after deploy (${HEALTH_URL})" >&2
|
||||||
echo "Last body: ${BODY:-<empty>}" >&2
|
echo "Last body: ${BODY:-<empty>}" >&2
|
||||||
echo "PM2 env PORT (should match .env):" >&2
|
echo "Listeners on PORT ${PORT}:" >&2
|
||||||
|
ss -tlnp 2>/dev/null | grep ":${PORT} " >&2 || netstat -tlnp 2>/dev/null | grep ":${PORT} " >&2 || true
|
||||||
pm2 env 0 2>/dev/null | grep -E '^PORT=' >&2 || true
|
pm2 env 0 2>/dev/null | grep -E '^PORT=' >&2 || true
|
||||||
pm2 logs next --lines 40 --nostream >&2 || true
|
pm2 logs next --lines 40 --nostream >&2 || true
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Reference in new issue
Block a user