diff --git a/.gitea/workflows/e2e.yml b/.gitea/workflows/e2e.yml index 39ad37f..1cfa3fe 100644 --- a/.gitea/workflows/e2e.yml +++ b/.gitea/workflows/e2e.yml @@ -1,12 +1,19 @@ # P5-06 — End-to-end test suite. # # Spec : docs/superpowers/specs/2026-05-07-p5-oss-readiness-design.md -# Stack: e2e/compose.e2e.yml (server + agent + rest-server) +# Stack: e2e/compose.e2e.yml (server + agent + rest-server + playwright) # Tests: e2e/playwright/tests/*.spec.ts # # Triggered on every PR into main and on workflow_dispatch. Runs # longer than the unit-test workflow (~3-4 minutes for a clean run); # kept separate so a slow e2e doesn't block the fast lint/test loop. +# +# Networking note: every interaction with the server (health probe, +# Playwright) happens from a container on the compose `rmnet` +# network, addressing the server as `http://server:8080`. We can't +# rely on `127.0.0.1:8080` because Gitea's runner executes steps +# inside its own container, where compose's host port-publish is +# not visible. name: e2e @@ -33,7 +40,8 @@ jobs: run: | set -eu for i in $(seq 1 30); do - if curl -fsS http://127.0.0.1:8080/api/version >/dev/null 2>&1; then + if docker run --rm --network e2e_rmnet curlimages/curl:8.10.1 \ + -fsS http://server:8080/api/version >/dev/null 2>&1; then echo "server up"; exit 0 fi sleep 2 @@ -60,22 +68,15 @@ jobs: - name: Start the agent run: docker compose -f e2e/compose.e2e.yml up -d agent - - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Install Playwright - working-directory: e2e/playwright + - name: Prepare report mounts run: | - npm install --no-audit --no-fund - npx playwright install --with-deps chromium + mkdir -p e2e/playwright/playwright-report e2e/playwright/test-results + chmod -R a+rwX e2e/playwright/playwright-report e2e/playwright/test-results - name: Run Playwright tests - working-directory: e2e/playwright env: - RM_BASE_URL: http://127.0.0.1:8080 RM_BOOTSTRAP_TOKEN: ${{ env.RM_BOOTSTRAP_TOKEN }} - run: npx playwright test + run: docker compose -f e2e/compose.e2e.yml run --rm playwright - name: Compose logs (on failure) if: failure() diff --git a/e2e/Dockerfile.playwright b/e2e/Dockerfile.playwright new file mode 100644 index 0000000..8689e6a --- /dev/null +++ b/e2e/Dockerfile.playwright @@ -0,0 +1,21 @@ +# Playwright runner for the e2e suite. Built and run by +# e2e/compose.e2e.yml so the test process sits on the same docker +# network as the server, agent, and rest-server. The previous setup +# ran Playwright on the workflow runner host and reached the server +# via 127.0.0.1:8080; that fails on Gitea's act-style runners +# because the workflow steps execute inside a runner container, +# not on the host where compose publishes its ports. + +FROM mcr.microsoft.com/playwright:v1.50.0-jammy + +WORKDIR /work + +# Install npm deps in a separate layer keyed off package.json so +# changes to specs don't bust the dep cache. +COPY e2e/playwright/package.json /work/package.json +RUN npm install --no-audit --no-fund + +COPY e2e/playwright/ /work/ + +ENV CI=1 +ENTRYPOINT ["npx", "playwright", "test"] diff --git a/e2e/compose.e2e.yml b/e2e/compose.e2e.yml index bb77b8d..7b94d27 100644 --- a/e2e/compose.e2e.yml +++ b/e2e/compose.e2e.yml @@ -63,6 +63,27 @@ services: - agent-state:/var/lib/restic-manager-agent networks: [rmnet] + # Playwright test runner. Profile-gated so `compose up` doesn't + # start it; CI runs it via `compose run --rm playwright`. Lives on + # rmnet so it can reach the server via its compose-network DNS + # name rather than depending on host port-publish (which doesn't + # work on Gitea's container-based runners). + playwright: + profiles: [test] + build: + context: .. + dockerfile: e2e/Dockerfile.playwright + environment: + RM_BASE_URL: "http://server:8080" + RM_BOOTSTRAP_TOKEN: "${RM_BOOTSTRAP_TOKEN:-}" + volumes: + - ./playwright/playwright-report:/work/playwright-report + - ./playwright/test-results:/work/test-results + depends_on: + - server + - agent + networks: [rmnet] + # One-shot init container that drops a couple of files into the # source volume so backups have something to snapshot. source-fixture: