Adds .github/workflows/e2e.yml adapted to this repo's backend/ + frontend/ layout: on every pull_request into main (or upstream-main), boot MinIO + local Supabase (loading backend/schema.sql), start the API and web dev servers, and run the Playwright suite, uploading the HTML report/traces on pass or fail. playwright.config.ts already disables its local webServer when CI=true, so the job owns the stack. docs/e2e-ci.md documents the one required secret (ANTHROPIC_API_KEY) and the branch-protection steps that make the 'e2e / playwright' check required, so a red run blocks the merge button. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.6 KiB
End-to-end tests in CI
The Playwright suite (e2e/) runs on every pull request through
.github/workflows/e2e.yml. This document covers the one repository secret it
needs and the branch-protection step that turns a red run into a blocked
merge — the workflow reports pass/fail on its own, but only branch protection
makes that check required.
What the workflow does
On every pull_request targeting main (or upstream-main, the fork mirror),
and on manual workflow_dispatch, the e2e / playwright job:
- installs the root (Playwright),
backend/, andfrontend/dependencies; - boots MinIO (S3-compatible object storage — three specs upload documents);
- boots local Supabase (Auth + Postgres) via the Supabase CLI and loads
backend/schema.sql— the same fresh-database schema the README tells a human to run; - writes
backend/.envandfrontend/.env.localfrom the live Supabase values; - starts the backend API (
:3001) and the Next.js web app (:3000), waits for both to be healthy; - runs
npx playwright testand uploads the HTML report + traces as an artifact (playwright-report) on both pass and fail.
e2e/auth.setup.ts bootstraps the shared test user (e2e@mike.local) against
the local Supabase admin API, so no login secret is needed — the credentials
baked into that file are the single source of truth.
Required secret
| Secret | Why | Without it |
|---|---|---|
ANTHROPIC_API_KEY |
The critical-path / chat specs send a message and assert a streamed answer, which needs a live model key. | Those chat specs fail; every other spec still runs. |
Add it under Settings → Secrets and variables → Actions → New repository secret. For pull requests opened from a fork, GitHub withholds secrets by default — a maintainer approves the run (or re-runs from the branch) so the key is available. Treat that approval as the point where the chat specs become enforceable for external contributions.
Make it merge-blocking
The workflow failing is not enough on its own — GitHub will still allow the merge unless the check is required. Enable branch protection once you have seen the suite go green a few times (it is environment-sensitive by nature):
- Settings → Branches → Add branch protection rule (or edit the rule for
main). - Enable Require status checks to pass before merging.
- Enable Require branches to be up to date before merging.
- In the checks search box add
e2e / playwright(the job appears in the list after it has run at least once on a PR). - Recommended alongside it: the unit/build check
backendand thelicense/clacheck. - Save. From now on a red e2e run blocks the Merge button.
Equivalent via the GitHub CLI (repo admin token required):
gh api -X PUT repos/OWNER/REPO/branches/main/protection \
-H "Accept: application/vnd.github+json" \
-f 'required_status_checks[strict]=true' \
-f 'required_status_checks[contexts][]=e2e / playwright' \
-f 'enforce_admins=true' \
-f 'required_pull_request_reviews[required_approving_review_count]=1' \
-f 'restrictions='
Running the suite locally
Locally, playwright.config.ts starts the backend and web dev servers for you
(webServer is only disabled when CI=true), so a full local stack plus:
npm ci
npx playwright install --with-deps chromium
npm run test:e2e # or test:e2e:ui / test:e2e:headed
e2e/auth.setup.ts reads SUPABASE_URL / SUPABASE_SECRET_KEY from the
environment or backend/.env, so a running local Supabase + a populated
backend/.env is all the setup needs.