`gitea.ref` differs between push (`refs/heads/<branch>`) and
pull_request (`refs/pull/N/head`) events even for the same commit,
so the two parallel runs land in different concurrency groups and
the Vite-on-:5173 collision is not suppressed. Switching the key to
the head sha (`gitea.event.pull_request.head.sha || gitea.sha`)
collapses both events into one bucket, leaving exactly one ui-test
alive per commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two ui-test jobs cannot coexist on the same host: Playwright's
`webServer` spec spawns `pnpm dev` on :5173, and on a host-mode
runner the port lives in the host namespace shared by every job.
ui-test #67 hit "Error: http://localhost:5173 is already used"
because a parallel job's Vite still held the port.
Two changes:
1. `concurrency: ui-test-${{ gitea.ref }}` with `cancel-in-progress:
true`. New push/PR runs against the same ref kill any earlier
ui-test before starting, so we never have two `pnpm dev`s alive
at once.
2. `pkill -f 'vite dev' || true` plus `fuser -k 5173/tcp` right
before Playwright. Defence in depth in case the concurrency
cancellation does not reap the spawned shell promptly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Under host-mode runner the default 6 workers + 1 retry consistently
land on ~7 flakies and an occasional hard fail per ui-test run
(ui-test #59 most recently). Workers share CPU and the host Docker
daemon with gitea, the long-lived dev stack, and the user's host
Caddy; the extra wall time from contention pushes individual
expectations past their timeouts.
Lower the worker cap to 4 to keep parallelism but give each worker
real CPU headroom, and raise retries to 4 so the rare slow page is
absorbed without surfacing as failure.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>