Add a workflow file under .github/workflows that triggers on pull requests, checks out the code, installs dependencies with npm ci, installs Playwright browsers, runs npx playwright test and uploads the HTML report. Then mark the job as a required status check so a red run blocks the merge.
What does the official starter workflow do?
The Playwright docs say that running npm init playwright@latest offers to create playwright.yml for you. The generated workflow runs on pushes and pull requests to main or master. Its steps are: check out the repository, set up Node.js, install dependencies with npm ci, install browsers with dependencies, run the tests, and upload the HTML report as an artifact kept for 30 days.
That is a good default. The rest of this post is about the choices around it.
Why pull_request and not only push?
A push trigger tests code after it lands. A pull_request trigger tests the merge result before it does. Use both if you want main protected from direct pushes too, but the pull request run is the gate.
For repositories that accept outside contributions, remember that workflows triggered from forks run with restricted permissions and no repository secrets by default. Do not work around that with the pull_request_target trigger unless you fully understand what code it checks out, because GitHub's own hardening guide warns about running untrusted code in privileged contexts.
What settings keep the job honest?
Three choices matter more than they look.
First, the timeout. The Playwright CI guide notes that the starter workflow does not set a job-level timeout and recommends setting globalTimeout in your Playwright config instead, so a hung run still produces a report. Pick a number a bit above your normal run time.
Second, permissions. Give the workflow the least it needs. A test job normally needs read access to repository contents and nothing else. Set that at the top of the file rather than relying on repository defaults.
Third, pinning. Third-party actions can change under a tag. GitHub's hardening guide recommends pinning an action to a full-length commit SHA if you need it to be immutable. The first-party checkout and setup actions are lower risk, but the same reasoning applies to anything from a smaller publisher.
How do you make failures easy to debug?
Upload the report even when tests fail. The starter workflow does this with a condition that runs the upload step unless the run was cancelled. Turn on traces for the first retry in your config so a failed test comes with a timeline you can open locally.
Retries deserve a rule. One retry in CI is normal for end to end tests that touch real browsers. Two or three turns flakiness into a habit. Track the tests that only pass on retry and fix them, since a suite people stop trusting stops being a gate.
A constructed example
A team has a checkout flow with twelve end to end tests and a run time near six minutes. They add the workflow, and the first week shows two tests failing on retry about one run in ten, both waiting on a network response. They replace fixed sleeps with waits on the specific response and the retries stop. The gate now blocks merges for real reasons. That is the outcome to aim for: fewer overrides, not more tests.
How to check or apply this
- Run
npm init playwright@latestor copy the starterplaywright.ymlinto.github/workflows. - Keep
npm cias the install step so the run uses your lockfile. - Set
globalTimeoutin the Playwright config and a sensiblepermissionsblock in the workflow. - Upload the report with a condition that runs on failure.
- In branch protection, require the Playwright job to pass before merging.
- Review flaky tests weekly and fix them rather than adding retries.
- Add dependency and secret scanning as separate required checks, so functional and security gates fail independently.
Safeguard can sit next to this job as another pull request gate, with policies that decide when a finding blocks a merge. Keep the test job itself simple.
Quick check
Do I need a service container or Docker for Playwright on GitHub Actions?
Not for the starter setup. The hosted Ubuntu runner can install the browsers with the install command and its dependencies option.
Should the Playwright job be a required check?
Yes, if you want it to gate merges. A workflow that can fail but does not block is a notification, not a gate.
Sources
- Playwright: Setting up CI
- Playwright: Continuous Integration
- GitHub Docs: Security hardening for GitHub Actions
- GitHub Docs: Building and testing Node.js
Last reviewed: 18 October 2026.