# 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 + 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

on:
  pull_request:
    branches: [main]
  workflow_dispatch:

# Force bash as the default shell — see ci.yml header.
defaults:
  run:
    shell: bash

jobs:
  e2e:
    name: Playwright vs docker-compose
    runs-on: ubuntu-latest
    container: gitea.dcglab.co.uk/steve/ci-runner-go:2026-05-08
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4

      - name: Build the e2e stack
        # --profile test pulls in the playwright service which is
        # otherwise gated. --pull refreshes base images so a bump
        # to the Dockerfile's FROM tag (e.g. mcr.microsoft.com/
        # playwright:vX.Y.Z-jammy) isn't masked by a stale runner
        # cache that still has the old tag's layers.
        run: docker compose --profile test -f e2e/compose.e2e.yml build --pull

      - name: Bring up the stack
        run: docker compose -f e2e/compose.e2e.yml up -d server rest-server source-fixture

      - name: Wait for server health
        run: |
          set -eu
          for i in $(seq 1 30); do
            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
          done
          echo "server didn't come up"; docker compose -f e2e/compose.e2e.yml logs server; exit 1

      - name: Capture bootstrap token from server logs
        id: bootstrap
        run: |
          set -eu
          for i in $(seq 1 15); do
            line=$(docker compose -f e2e/compose.e2e.yml logs server 2>&1 | grep -E 'bootstrap token' -A2 | grep -Eo '[a-zA-Z0-9_-]{40,}' | head -1 || true)
            if [ -n "$line" ]; then
              echo "RM_BOOTSTRAP_TOKEN=$line" >> "$GITHUB_ENV"
              echo "got bootstrap token (${#line} chars)"
              exit 0
            fi
            sleep 1
          done
          echo "bootstrap token not found in logs"
          docker compose -f e2e/compose.e2e.yml logs server
          exit 1

      - name: Start the agent
        run: docker compose -f e2e/compose.e2e.yml up -d agent

      - name: Run Playwright tests
        id: playwright
        env:
          RM_BOOTSTRAP_TOKEN: ${{ env.RM_BOOTSTRAP_TOKEN }}
        # --name pins a stable container ID so the next step can
        # docker cp out of it before tear-down. We deliberately
        # drop --rm so the container survives the test exit; the
        # tear-down step removes it.
        run: docker compose -f e2e/compose.e2e.yml run --name e2e-pw playwright

      - name: Extract Playwright report
        if: always() && steps.playwright.outcome != 'skipped'
        run: |
          mkdir -p e2e/playwright/playwright-report e2e/playwright/test-results
          docker cp e2e-pw:/work/playwright-report/. e2e/playwright/playwright-report/ || true
          docker cp e2e-pw:/work/test-results/. e2e/playwright/test-results/ || true

      - name: Show Playwright failure context (on failure)
        if: failure()
        run: |
          set +e
          shopt -s nullglob globstar
          for f in e2e/playwright/test-results/**/error-context.md; do
            echo "::group::$f"
            cat "$f"
            echo "::endgroup::"
          done
          echo "Failure attachments (download via the playwright-report artifact):"
          find e2e/playwright/test-results \( -name '*.png' -o -name '*.webm' -o -name 'trace.zip' \) -printf '  %p\n' | sort

      - name: Compose logs (on failure)
        if: failure()
        run: |
          docker compose -f e2e/compose.e2e.yml logs --tail=200 server
          docker compose -f e2e/compose.e2e.yml logs --tail=200 agent
          docker compose -f e2e/compose.e2e.yml logs --tail=200 rest-server

      - name: Upload Playwright report (on failure)
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: |
            e2e/playwright/playwright-report
            e2e/playwright/test-results
          retention-days: 7

      - name: Tear down
        if: always()
        run: |
          docker rm -f e2e-pw 2>/dev/null || true
          docker compose -f e2e/compose.e2e.yml down -v
