evOo-local/scripts/free-e2e-ports.sh
cynarAI 5cd1bc906f ci: Product CI merge gate and Autopilot auto-merge (#84)
* ci: add Product CI merge gate and Autopilot auto-merge path

Aggregate lint, typecheck, builds, unit, Postgres journeys, and Web E2E
into a single Product CI check for branch protection. Soft-fail artifact
uploads and skip headless macOS screenshots so infra noise does not block
merge. Add autopilot/auto-merge workflow and MERGE_GATES.md.

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(ci): keep autopilot auto-merge inert without label

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(ci): run autopilot auto-merge on self-hosted runner

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* 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>

* fix(web): stabilize message More menu Escape in hover E2E

The desktop hover spec assumed Escape always closed the first page-level
menu within one keypress. On self-hosted Chromium the Copy menu could stay
open while the rail remained visible, failing getByRole('menu') count.

Wait for the Copy item to prove the menu opened, then retry Escape until
that item hides while asserting the More control stays on the hover rail.

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(web): retry sign-up navigation in Playwright helpers

Late-suite specs can miss the sign-up heading when Vite is still
warming on self-hosted runners. Retry goto until the form renders
instead of failing once at the default timeout.

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
2026-09-24 00:57:10 +02: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