This script runs inside the runner's own job container and talks to the
host's docker daemon over a mounted socket (docker-outside-of-docker). A
bind mount path only exists inside this job container, not on the host the
daemon resolves it against, so docker run -v failed with ENOENT. docker cp
copies file contents instead, sidestepping the path mismatch.
npx resolved the registry's generic "playwright" package instead of the
locally installed @playwright/test bin, triggering an unwanted fresh install
and "No tests found". npm run e2e uses the project's own node_modules/.bin
unambiguously.
Playwright's bundled Chromium is glibc-only and --with-deps assumes apt -
both fail on this musl/Alpine runner. Run the e2e leg in
mcr.microsoft.com/playwright (browsers preinstalled, pinned to the exact
resolved @playwright/test version) instead, reachable at the same bridge
gateway IP as the rest of the QA stack.
Same runner dotnet-install.sh detects as musl and picks linux-musl-x64 for -
the glibc node tarball can't even exec there ("env: can't execute 'node'").
The runner executes each job in its own container on docker's default bridge
network, so "localhost" never resolves to the docker host - smoke-qa's direct
Postgres connection and Playwright/API HTTP calls need the bridge gateway IP
instead. Bind the db port to that same gateway IP (not 0.0.0.0) so it stays
reachable only from sibling containers, not off-box.
The self-hosted qa runner's minimal image lacked libstdc++/libgcc, which
dotnet fails on with an obscure symbol-relocation error rather than a
clear "missing dependency" message.
Existing coverage was one integration test and zero e2e tests. Adds the thin,
high-value integration/e2e layer unit tests can't reach (real Postgres wire
contract, real browser flows) and wires it as a post-deploy smoke gate.
- Seed a deterministic dev/QA admin user and fixed Development env key so
HTTP-only tests can authenticate without per-run registration.
- Expand the API integration suite: disabled-flag, unauthorized access,
environment-document bootstrap, identity-override precedence, and auth
login scenarios, reusing the existing black-box HTTP+Npgsql harness.
- Add a Playwright suite for the admin SPA: login, nav, project/environment
context selection, and feature create/toggle, against the real API.
- Bind QA Postgres to 127.0.0.1 for direct seeding, add smoke-qa.sh and an
ensure_node() bootstrap (the qa runner has no Node today), and wire a new
smoke-qa CI job after deploy-qa.
The self-hosted runner runs in its own container on a separate bridge
network, so curling localhost:$QA_ADMIN_PORT hit the runner's own loopback
instead of the docker host's published port, never the QA stack.
Exec into the admin container and curl its own localhost instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The app maps health checks at /health (ServiceDefaults), not /api/v1/health.
Compose healthcheck and deploy-qa.sh's wait-loop both hit the wrong path.
Also add an nginx location for /health since it lives outside the /api
prefix that the admin proxy otherwise forwards unchanged.
Gitea runner build failed with "dotnet: command not found". Added
ensure_dotnet() to lib.sh, using the vendored dotnet-install.sh to
bootstrap the SDK into .dotnet/ when not already on PATH, called from
build.sh/test.sh/prepush.sh. Also trigger CI on build-runner-fix to
verify the fix.