refactor: make Webhook Detail acquisition truthful #408
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Nightly E2E | |
| # Exercises the full published stack (dashboard image + cycles-server + | |
| # cycles-server-admin + redis) through the dashboard's built-in nginx. | |
| # Catches plumbing-layer defects that unit tests and Vite-based dev work | |
| # don't see — specifically the class of bugs that produced v0.1.25.22's | |
| # nginx proxy_pass path-stripping regression. | |
| # Cancel in-flight runs when a newer commit lands on the same ref. | |
| # Three rapid pushes to the same PR don't need three parallel compose | |
| # spin-ups — the latest one supersedes the others. | |
| concurrency: | |
| group: e2e-${{ github.ref }} | |
| cancel-in-progress: true | |
| on: | |
| schedule: | |
| # Daily at 06:00 UTC — off-hours for most contributors and avoids | |
| # the GitHub Actions queue rush at the top of the hour. | |
| - cron: '0 6 * * *' | |
| workflow_dispatch: | |
| # Also run on PRs that touch the highest-risk plumbing files, so | |
| # regressions are caught at review time. Scoped narrowly on purpose — | |
| # we don't want to add 3+ minutes of compose stack spin-up to every PR. | |
| pull_request: | |
| paths: | |
| - 'default.conf.template' | |
| - 'Dockerfile' | |
| - 'docker-compose*.yml' | |
| - 'src/api/client.ts' | |
| - 'src/views/**' | |
| - 'src/components/**' | |
| # Style changes can break visual rendering (e.g. dark-mode cascade | |
| # regressions from @apply-inlined component classes) — Vitest and | |
| # axe both miss these, Playwright flows catch them by running the | |
| # actual dashboard in a real browser. | |
| - 'src/style.css' | |
| - 'src/stores/**' | |
| - 'src/router.ts' | |
| - '.github/workflows/e2e.yml' | |
| - 'scripts/e2e-probes.sh' | |
| - 'tests/e2e/**' | |
| - 'playwright.config.ts' | |
| permissions: read-all | |
| jobs: | |
| e2e: | |
| name: Compose stack + HTTP probes | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| # Needed for ghcr.io image pulls (cycles-server, cycles-server-admin). | |
| packages: read | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| # Authenticate to ghcr so we can pull the backend images. The | |
| # dashboard image is built locally from this checkout so we test | |
| # the current source, not a previously-published build. | |
| - name: Log in to ghcr.io | |
| uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 | |
| # Build the dashboard image from current source. docker-compose.yml | |
| # uses `build: .` for the dashboard service, so `compose up --build` | |
| # will pick this up; explicit build step keeps build output in the | |
| # logs for easier diagnosis on failure. | |
| - name: Build dashboard image | |
| run: docker compose -f docker-compose.yml build dashboard | |
| # `--wait` blocks until every service is "ready" — healthy for | |
| # services with a healthcheck defined, started for ones without. | |
| # This is exactly the semantics we want, and matches what | |
| # `depends_on: condition: service_healthy` uses internally. | |
| # `--wait-timeout 120` caps cold-start waits at 2 minutes; each | |
| # JVM service declares start_period: 30s + interval: 10s, so 120s | |
| # is a comfortable ceiling on a CI runner. Without --wait, we | |
| # previously hand-rolled a polling loop that misread services | |
| # lacking a healthcheck (e.g. dashboard) as "never healthy" and | |
| # looped forever. | |
| - name: Start compose stack (waits for ready) | |
| env: | |
| ADMIN_API_KEY: admin-bootstrap-key | |
| run: | | |
| docker compose -f docker-compose.yml up -d --wait --wait-timeout 120 | |
| docker compose -f docker-compose.yml ps | |
| - name: Run E2E probes | |
| env: | |
| ADMIN_API_KEY: admin-bootstrap-key | |
| DASHBOARD_URL: http://localhost:8080 | |
| run: bash scripts/e2e-probes.sh | |
| # Playwright runs after the HTTP probes pass. Probes catch | |
| # routing/plumbing regressions; Playwright catches JS-layer bugs | |
| # (e.g. the v0.1.25.22 sort-accessor class). Both layers share | |
| # the same compose stack — no extra spin-up cost. | |
| - name: Set up Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Install npm dependencies | |
| run: npm ci | |
| - name: Cache Playwright browsers | |
| id: playwright-cache | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| - name: Install Playwright browsers | |
| if: steps.playwright-cache.outputs.cache-hit != 'true' | |
| run: npx playwright install --with-deps chromium | |
| - name: Install Playwright system deps (when cached) | |
| if: steps.playwright-cache.outputs.cache-hit == 'true' | |
| run: npx playwright install-deps chromium | |
| - name: Run Playwright tests | |
| env: | |
| ADMIN_API_KEY: admin-bootstrap-key | |
| DASHBOARD_URL: http://localhost:8080 | |
| CI: 'true' | |
| run: npx playwright test | |
| # On failure, surface each container's logs as a workflow artifact | |
| # so the person triaging doesn't need to reproduce locally. | |
| - name: Capture compose logs on failure | |
| if: failure() | |
| run: | | |
| mkdir -p e2e-logs | |
| for svc in dashboard cycles-admin cycles-server redis; do | |
| docker compose -f docker-compose.yml logs "$svc" > "e2e-logs/$svc.log" 2>&1 || true | |
| done | |
| docker compose -f docker-compose.yml ps > e2e-logs/compose-ps.txt 2>&1 || true | |
| - name: Upload compose logs on failure | |
| if: failure() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: e2e-compose-logs | |
| path: e2e-logs/ | |
| retention-days: 14 | |
| # Playwright produces its own HTML report + traces/screenshots/ | |
| # videos (retained on failure per playwright.config.ts). Upload | |
| # separately so triage can open the Playwright report directly | |
| # and click through to the failing step's trace. | |
| - name: Upload Playwright report on failure | |
| if: failure() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: playwright-report | |
| path: | | |
| playwright-report/ | |
| test-results/ | |
| retention-days: 14 | |
| - name: Tear down | |
| if: always() | |
| run: docker compose -f docker-compose.yml down -v |