From 2f05ab6a817e5198e2a740706976108b7b1edde1 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 2 Oct 2026 15:41:55 +0000 Subject: [PATCH] ci: give each runner on a shared host its own E2E ports Two Linux runners live on the same host. Every Web E2E job first frees "stale" listeners on the fixed ports 3110, 3111, 5180 and 4321 with fuser -k, so a job starting on the second runner killed the Vite server of the job already running on the first one. The victim died with SIGKILL (exit 137), and its remaining tests failed on reloads that could no longer reach a server. This is what made the Web E2E run on this PR red, and it explains the recurring reload failures on main whenever two runs overlapped. The workflow now derives API_PORT, WEB_PORT and WWW_PORT from the runner name (suffix -N means an offset of N times 100), and the port-freeing script follows those settings instead of a hard-coded list. The harness, Vite, the API and the marketing site already read these variables. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u --- .github/workflows/playwright.yml | 16 ++++++++++++++++ scripts/free-e2e-ports.sh | 13 ++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 00cd53b..24ee373 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -111,6 +111,22 @@ jobs: env: BOX_API_KEY: ${{ secrets.BOX_API_KEY }} run: test -n "$BOX_API_KEY" + - name: Pick E2E ports for this runner + # Several runners share one host. Each runner gets its own port set so the + # port-freeing steps and the harness never touch another job's servers. + run: | + set -euo pipefail + suffix="${RUNNER_NAME##*-}" + offset=0 + if [[ "$suffix" =~ ^[0-9]+$ ]]; then + offset=$((suffix * 100)) + fi + { + echo "API_PORT=$((3110 + offset))" + echo "WEB_PORT=$((5180 + offset))" + echo "WWW_PORT=$((4321 + offset))" + } >> "$GITHUB_ENV" + echo "E2E ports for ${RUNNER_NAME}: api $((3110 + offset)), web $((5180 + offset)), www $((4321 + offset))" - name: Free stale E2E ports run: bash scripts/free-e2e-ports.sh - name: Run Playwright tests diff --git a/scripts/free-e2e-ports.sh b/scripts/free-e2e-ports.sh index 754bcf8..32c29d8 100755 --- a/scripts/free-e2e-ports.sh +++ b/scripts/free-e2e-ports.sh @@ -1,11 +1,22 @@ #!/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) -readonly E2E_PORTS=(3110 3111 5180 4321) +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)"