pr-preview-e2e #228
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: pr-preview-e2e | |
| # Run the Playwright e2e suite against the PR preview URL once the | |
| # preview deploy finishes. This is where Stage-10's parquet decoder | |
| # (and every other UI feature) gets validated end-to-end on the actual | |
| # bundle the reviewer will load — `pnpm preview` locally can't catch | |
| # CORS, CDN, or Dropbox-fetch issues. Failures land as a failed check | |
| # on the PR with the trace attached as a workflow artifact. | |
| on: | |
| workflow_run: | |
| workflows: ['pr-preview'] | |
| types: [completed] | |
| permissions: | |
| contents: read | |
| actions: read | |
| checks: write | |
| pull-requests: write | |
| jobs: | |
| e2e: | |
| # Only run if the preview deploy itself succeeded — otherwise the URL | |
| # is stale and the run is meaningless. | |
| if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Resolve PR number | |
| id: pr | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # The triggering workflow_run carries the head SHA; resolve the | |
| # PR number from it. (`event.workflow_run.pull_requests` is | |
| # often empty for fork PRs; using `gh pr list --search` is the | |
| # robust path for in-repo PRs, which is what `pr-preview.yml` | |
| # restricts to anyway.) | |
| PR=$(gh pr list --repo "${{ github.repository }}" --search "${{ github.event.workflow_run.head_sha }}" --state open --json number --jq '.[0].number') | |
| if [ -z "$PR" ] || [ "$PR" = "null" ]; then | |
| echo "::error::Could not resolve PR number for SHA ${{ github.event.workflow_run.head_sha }}" | |
| exit 1 | |
| fi | |
| echo "number=$PR" >> $GITHUB_OUTPUT | |
| echo "Resolved PR #$PR" | |
| - name: Open PR check run | |
| id: check | |
| # workflow_run-triggered runs don't surface as PR checks | |
| # automatically; the GitHub Actions UI only links the in-progress | |
| # job to the workflow_run that fired it. Creating an explicit | |
| # check_run on the PR head SHA gives reviewers a visible status | |
| # entry under the PR's "Checks" tab while the job runs. | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { data: cr } = await github.rest.checks.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| name: 'pr-preview-e2e', | |
| head_sha: '${{ github.event.workflow_run.head_sha }}', | |
| status: 'in_progress', | |
| details_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| output: { | |
| title: 'Playwright e2e against PR preview', | |
| summary: `Running the suite against the deployed PR preview URL. [Workflow run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}).`, | |
| }, | |
| }); | |
| core.setOutput('id', cr.id); | |
| - name: Checkout PR head | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| fetch-depth: 1 | |
| - name: Set up Node 20 + pnpm | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Enable pnpm | |
| run: npm install --global pnpm@10 | |
| - name: Install site deps | |
| working-directory: site | |
| run: pnpm install --frozen-lockfile | |
| - name: Install Playwright browsers | |
| working-directory: site | |
| # webkit is needed for the Stage-24 iphone-webkit regression guard | |
| # (specs/024-fix-ios-safari-load) — iPhone Safari is a WebKit engine | |
| # that the chromium project can't reproduce. | |
| run: pnpm exec playwright install chromium webkit --with-deps | |
| - name: Wait for PR preview to be live | |
| env: | |
| PR_NUMBER: ${{ steps.pr.outputs.number }} | |
| run: | | |
| # The pr-preview workflow's gh-pages push can lag behind the | |
| # workflow_run completion event by ~30 s. Poll until the preview | |
| # responds 200 OR until we give up (5 min). | |
| # NOTE: gh-pages serves a CNAME redirect to the custom domain | |
| # (abstractatlas.brainkb.org), so probe the CNAME directly — | |
| # `<owner>.github.io/<repo>/...` 301s to it and pollutes the | |
| # probe output. `curl -L` would also work but the CNAME-direct | |
| # path is what Playwright will actually hit below. | |
| URL="https://abstractatlas.brainkb.org/pr-${PR_NUMBER}/ohbm2026/" | |
| echo "Probing $URL" | |
| for i in $(seq 1 30); do | |
| code=$(curl -s -o /dev/null -w '%{http_code}' "$URL" || true) | |
| if [ "$code" = "200" ]; then | |
| echo "Preview live after ${i} polls." | |
| break | |
| fi | |
| echo " [$i/30] HTTP $code — sleeping 10s" | |
| sleep 10 | |
| done | |
| - name: Run Playwright e2e against the preview URL | |
| working-directory: site | |
| env: | |
| # `PLAYWRIGHT_BASE_URL` is the FULL URL of the conference home | |
| # for the PR preview — origin + per-PR prefix + `/ohbm2026/`. | |
| # workflow_run reads THIS file from main (not the PR head), so | |
| # any future change to this env var needs to land via a | |
| # bootstrap PR before the consuming spec refactor (see #25 → | |
| # #24). Specs in the refactored suite resolve `./about/` and | |
| # `./abstract/<id>/` against this baseURL, so the suite hits | |
| # the PR deploy instead of silently falling through to prod. | |
| PLAYWRIGHT_BASE_URL: https://abstractatlas.brainkb.org/pr-${{ steps.pr.outputs.number }}/ohbm2026/ | |
| UI_DATA_AVAILABLE: '1' | |
| run: pnpm exec playwright test --project=chromium | |
| - name: Run Stage-24 WebKit/iPhone regression guard against the preview | |
| working-directory: site | |
| # specs/024-fix-ios-safari-load (FR-006): the iPhone-Safari load + | |
| # navigation-crash fix is WebKit-specific, so guard it on the REAL | |
| # WebKit engine. Scoped to the four Stage-24 specs so the existing | |
| # chromium suite is untouched. Runs against the same deployed preview | |
| # (R2 data-host CORS resolves on this origin, not on localhost). | |
| env: | |
| PLAYWRIGHT_BASE_URL: https://abstractatlas.brainkb.org/pr-${{ steps.pr.outputs.number }}/ohbm2026/ | |
| UI_DATA_AVAILABLE: '1' | |
| run: pnpm exec playwright test --project=iphone-webkit ios-ohbm-load ios-load-failure ios-navigation ios-siblings | |
| - name: Upload Playwright report on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playwright-report-pr-${{ steps.pr.outputs.number }} | |
| path: site/playwright-report/ | |
| retention-days: 14 | |
| - name: Close PR check run | |
| if: always() && steps.check.outputs.id | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const conclusion = '${{ job.status }}' === 'success' ? 'success' : 'failure'; | |
| await github.rest.checks.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| check_run_id: ${{ steps.check.outputs.id }}, | |
| status: 'completed', | |
| conclusion, | |
| output: { | |
| title: `Playwright e2e: ${conclusion}`, | |
| summary: `[Workflow run](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}). On failure the Playwright report is attached as a workflow artifact.`, | |
| }, | |
| }); |