evOo-local/scripts/free-e2e-ports.sh
Cursor Agent f1bd94dda2 fix(ci): free stale E2E ports before Playwright bind on Linux
Self-hosted evoo-ci runners can retain listeners on harness ports
(3110 API, 5180 web, 4321 marketing, 3111 device control) after a
failed run, causing EADDRINUSE before the next job. Add a guarded
free-e2e-ports.sh that uses fuser on Linux only and never touches
live dev ports 3100/5173. Wire it into the Playwright workflow and
the E2E harness with clear logging.

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
2026-09-23 21:51:52 +00:00

48 lines
1.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Free stale listeners on dedicated Playwright/E2E ports before harness bind.
# Never touches live dev stack ports 3100 (API) or 5173 (web).
set -euo pipefail
readonly LIVE_PORTS=(3100 5173)
readonly E2E_PORTS=(3110 3111 5180 4321)
if [[ "$(uname -s)" != "Linux" ]]; then
echo "free-e2e-ports: skip (not Linux)"
exit 0
fi
if ! command -v fuser >/dev/null 2>&1; then
echo "free-e2e-ports: warning: fuser not found; cannot pre-free E2E ports" >&2
exit 0
fi
for port in "${LIVE_PORTS[@]}"; do
for e2e_port in "${E2E_PORTS[@]}"; do
if [[ "$port" -eq "$e2e_port" ]]; then
echo "free-e2e-ports: internal error: live port $port must not be in E2E_PORTS" >&2
exit 1
fi
done
done
echo "free-e2e-ports: clearing stale listeners on E2E ports (${E2E_PORTS[*]}); live ports ${LIVE_PORTS[*]} untouched"
for port in "${E2E_PORTS[@]}"; do
spec="${port}/tcp"
if fuser "$spec" >/dev/null 2>&1; then
echo "free-e2e-ports: port $port in use:"
fuser -v "$spec" 2>&1 || true
echo "free-e2e-ports: killing processes on port $port (fuser -k)"
fuser -k "$spec" 2>&1 || true
sleep 0.25
if fuser "$spec" >/dev/null 2>&1; then
echo "free-e2e-ports: warning: port $port still in use after fuser -k" >&2
else
echo "free-e2e-ports: port $port is now free"
fi
else
echo "free-e2e-ports: port $port already free"
fi
done