#!/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). # The ports follow API_PORT, WEB_PORT and WWW_PORT so that runners sharing one host, # each with its own port set, never kill another job's servers. set -euo pipefail for setting in API_PORT WEB_PORT WWW_PORT; do value="${!setting:-}" if [[ -n "$value" && ! "$value" =~ ^[0-9]+$ ]]; then echo "free-e2e-ports: $setting must be a port number, got: $value" >&2 exit 1 fi done readonly LIVE_PORTS=(3100 5173) api_port="${API_PORT:-3110}" readonly E2E_PORTS=("$api_port" "$((api_port + 1))" "${WEB_PORT:-5180}" "${WWW_PORT:-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