Files
supabase/.github/workflows/docs-e2e.yml
T
Alaister YoungandAlaister Young f877413e05 fix(docs ci): report Docs E2E check on every PR (#48681)
\"Docs E2E\" is a required status check on master, but the workflow only
triggered on docs-related paths. A required check whose workflow never
starts creates no check run at all, so every non-docs PR sat blocked on
\"Expected — waiting for status to be reported\" (e.g. #48677).

The fix relies on the asymmetry in how branch protection treats the two
kinds of skipping: a job skipped via an `if:` condition still reports a
check run (counted as passing), while a workflow filtered out by
`paths:` reports nothing.

**Changed:**
- Dropped the `paths:` filter from the `pull_request` trigger — the
workflow now runs on every PR to master
- Added a `dorny/paths-filter` step (same pattern as
`studio-e2e-test.yml`) carrying the exact path list the trigger used to
have; it runs before checkout using the API, so non-docs PRs skip the
expensive full-history checkout entirely and report green in seconds
- Folded the later \"Detect docs app changes\" step into the same filter
(`docs_app` output)
- Flipped downstream step guards from `skip != 'true'` to `skip ==
'false'` so they stay off when the scope step itself was skipped (its
output is empty then, and empty `!= 'true'` would have run them)

This also fixes draft PRs: the job-level draft condition now produces a
skipped-but-reported check instead of nothing, and `ready_for_review`
triggers a real run.

No behavior change for docs PRs or `workflow_dispatch` runs. The
required-check context (`Docs E2E`) keeps its name.

## To test

- On this PR (docs-related since it edits the workflow): the full suite
should run as before
- On a non-docs PR after merge: \"Docs E2E\" reports green in seconds
instead of hanging as \"Expected\"
- On a draft PR: check reports as skipped, run happens on
ready-for-review

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
* Documentation end-to-end checks now report a status for every
qualifying pull request.
* Documentation changes automatically run the relevant browser tests and
upload test reports.
* Pull requests without documentation changes receive a successful
skipped check.
* Preview environment validation now runs only when documentation
changes are detected.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-08-04 14:37:12 +07:00

199 lines
8.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Docs E2E Tests
# "Docs E2E" is a required status check on master, so this workflow must
# produce a check run on every PR — a `paths` trigger filter would leave
# non-docs PRs waiting on a check that never reports. Path scoping happens
# in the "Detect changed paths" step instead; when nothing docs-related
# changed, the remaining steps are skipped and the check reports green.
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
branches: ['master']
workflow_dispatch:
inputs:
base_url:
description: 'Base URL to test against'
required: false
default: 'https://supabase.com'
type: string
page_paths:
description: 'Comma-separated /docs/... paths to test (required for manual runs)'
required: false
default: ''
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
statuses: read
pull-requests: read
env:
CI: true
jobs:
e2e:
name: Docs E2E
if: github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false
timeout-minutes: 30
runs-on: blacksmith-4vcpu-ubuntu-2404
steps:
# Runs before checkout — reads the PR file list from the API. `docs`
# mirrors the path scope this workflow used to have as a trigger filter;
# `docs_app` decides whether a Vercel docs preview exists to test against.
- name: Detect changed paths
id: changes
if: github.event_name == 'pull_request'
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
filters: |
docs:
- 'apps/docs/content/guides/**/*.mdx'
- 'apps/docs/content/troubleshooting/**/*.mdx'
- 'apps/docs/content/_partials/**'
- 'e2e/docs/features/**'
- 'e2e/docs/utils/**'
- 'e2e/docs/scripts/**'
- 'e2e/docs/playwright.config.ts'
- 'e2e/docs/package.json'
- 'e2e/docs/tsconfig.json'
- 'pnpm-lock.yaml'
- '.github/workflows/docs-e2e.yml'
docs_app:
- 'apps/docs/**'
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
if: github.event_name == 'workflow_dispatch' || steps.changes.outputs.docs == 'true'
with:
persist-credentials: false
# Need full history on PRs so we can diff against the base branch.
# Use string '0' — numeric 0 is falsy in GitHub Actions expressions.
fetch-depth: ${{ github.event_name == 'pull_request' && '0' || '1' }}
sparse-checkout: |
e2e/docs
scripts
patches
apps/docs/content/guides
apps/docs/content/troubleshooting
apps/docs/content/_partials
apps/docs/scripts/federated-content/sources
- name: Use Node.js
if: github.event_name == 'workflow_dispatch' || steps.changes.outputs.docs == 'true'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
# Map changed owned content (guides, troubleshooting, partials) to page
# URLs. Harness-only PRs resolve to skip=true and exit before Playwright.
- name: Resolve docs E2E scope
id: scope
if: github.event_name == 'workflow_dispatch' || steps.changes.outputs.docs == 'true'
env:
EVENT_NAME: ${{ github.event_name }}
BASE_REF: ${{ github.base_ref }}
PAGE_PATHS_INPUT: ${{ inputs.page_paths }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
if [ -z "$PAGE_PATHS_INPUT" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "paths=" >> "$GITHUB_OUTPUT"
echo "Manual run requires the page_paths input."
exit 0
fi
echo "skip=false" >> "$GITHUB_OUTPUT"
printf 'paths=%s\n' "$PAGE_PATHS_INPUT" >> "$GITHUB_OUTPUT"
exit 0
fi
git diff --name-only --diff-filter=ACMR "origin/$BASE_REF"...HEAD \
| node --experimental-strip-types e2e/docs/scripts/resolve-docs-scope.ts
- name: Skip Playwright (no in-scope pages)
if: steps.scope.outputs.skip == 'true'
run: echo "No in-scope docs pages changed; skipping Playwright suite."
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
if: steps.scope.outputs.skip == 'false'
name: Install pnpm
with:
run_install: false
- name: Enable pnpm store cache
if: steps.scope.outputs.skip == 'false'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
# Vercel skips the docs preview when a PR only changes the harness
# (e2e/docs, workflow), so wait for a preview only when apps/docs changed.
#
# Vercel's GitHub App stopped writing GitHub Deployment objects on
# 2026-02-17 (broken app auth), so vercel/wait-for-deployment-action
# times out polling that API even though the preview builds fine.
# Poll the "Vercel – docs" commit status instead — Vercel keeps posting
# those — then resolve the deployment it points to via Vercel's own API
# to get the actual preview URL. See scripts/waitForVercelDocsPreview.js.
- name: Wait for Vercel docs preview
if: steps.scope.outputs.skip == 'false' && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && steps.changes.outputs.docs_app == 'true'
id: deployment
run: node scripts/waitForVercelDocsPreview.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
- name: Resolve base URL
if: steps.scope.outputs.skip == 'false'
id: base-url
env:
EVENT_NAME: ${{ github.event_name }}
BASE_URL_INPUT: ${{ inputs.base_url }}
DEPLOYMENT_URL: ${{ steps.deployment.outputs.deployment-url }}
DOCS_APP_CHANGED: ${{ steps.changes.outputs.docs_app }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
printf 'url=%s\n' "$BASE_URL_INPUT" >> "$GITHUB_OUTPUT"
echo "use_bypass=false" >> "$GITHUB_OUTPUT"
elif [ "$DOCS_APP_CHANGED" = "true" ] && [ -n "$DEPLOYMENT_URL" ]; then
printf 'url=%s\n' "$DEPLOYMENT_URL" >> "$GITHUB_OUTPUT"
echo "use_bypass=true" >> "$GITHUB_OUTPUT"
else
# Harness-only PRs have no docs preview; test against production.
echo "url=https://supabase.com" >> "$GITHUB_OUTPUT"
echo "use_bypass=false" >> "$GITHUB_OUTPUT"
fi
- name: Install dependencies
if: steps.scope.outputs.skip == 'false'
run: pnpm install --frozen-lockfile --filter=e2e-docs...
- name: Install Playwright Chromium
if: steps.scope.outputs.skip == 'false'
run: pnpm -C e2e/docs exec playwright install chromium --with-deps --only-shell
- name: Run docs E2E
if: steps.scope.outputs.skip == 'false'
working-directory: e2e/docs
run: pnpm run e2e:docs
env:
PLAYWRIGHT_BASE_URL: ${{ steps.base-url.outputs.url }}
DOCS_E2E_PAGE_PATHS: ${{ steps.scope.outputs.paths }}
VERCEL_AUTOMATION_BYPASS_SECRET: ${{ steps.base-url.outputs.use_bypass == 'true' && secrets.VERCEL_AUTOMATION_BYPASS_DOCS || '' }}
- name: Upload Playwright report
if: failure() && steps.scope.outputs.skip == 'false'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: docs-playwright-report
path: |
e2e/docs/playwright-report/
e2e/docs/test-results/
retention-days: 7