test(ui): isolate the fixture port so parallel runs stop colliding
CI / check (push) Successful in 29s
CI / tests-imaging-browsers (push) Successful in 1m37s
CI / tests-unit (push) Successful in 2m4s
CI / tests-integration (push) Successful in 2m12s
CI / tests-quality (push) Successful in 55s
CI / tests-ui (push) Successful in 4m31s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m39s

The self-hosted CI runner packs several jobs onto the shared host network
(capacity 4). The UI suite pinned the fixture server to 127.0.0.1:3107 and set
reuseExistingServer: true, so overlapping runs fought over the bind: one job
won it, and every browser in the other got "connection refused" on all four
projects. Pass one random high port per run through the environment (shared by
the main process and its worker) and only reuse an existing server outside CI.
Verified with the full ui suite: 150 passed, 2 skipped.
This commit is contained in:
openhands committed 2026-10-19 20:16:28 +02:00
1 parent 3bc218ba16
commit 1e81cac504
1 file changed
+20 -4
+20 -4
View File
@@ -1,8 +1,24 @@
import { randomInt } from "node:crypto";
import { defineConfig } from "@playwright/test";
const port = Number(process.env.UI_TEST_PORT || 3107);
if (!Number.isInteger(port) || port < 1024 || port > 65535)
throw Error("Invalid UI_TEST_PORT");
// The fixture server binds a loopback port. The CI runner packs several jobs
// onto the shared host network (capacity > 1), so a fixed port makes concurrent
// runs fight over the bind: one wins, the other's browser then gets
// "connection refused". Pick one random high port for the whole run and pass it
// to every worker through the environment, unless a port is pinned explicitly
// (e.g. a developer reusing a manually started fixture server).
function fixturePort() {
const requested = Number(process.env.UI_TEST_PORT);
if (Number.isInteger(requested) && requested >= 1024 && requested <= 65535)
return requested;
const shared = Number(process.env.PW_UI_TEST_PORT);
if (Number.isInteger(shared) && shared >= 1024 && shared <= 65535)
return shared;
const port = randomInt(30000, 50000);
process.env.PW_UI_TEST_PORT = String(port);
return port;
}
const port = fixturePort();
const baseURL = `http://127.0.0.1:${port}`;
export default defineConfig({
testDir: "./e2e/ui",
@@ -65,7 +81,7 @@ export default defineConfig({
command: "node e2e/ui/fixture-server.mjs",
url: `${baseURL}/health`,
timeout: 120000,
reuseExistingServer: true,
reuseExistingServer: !process.env.CI,
env: { UI_TEST_PORT: String(port) },
},
});