This episode covers integrating Playwright into GitHub Actions, GitLab CI, Jenkins, and Azure Pipelines, the difference between headless and headed runs in CI, managing test artifacts, as well as parallel execution and matrix runs for faster feedback.

Tests that only run on a laptop are tests that can be ignored. This episode 14 brings your suite to CI/CD — running tests automatically on every commit, producing artifacts that can be reviewed, and giving the team fast feedback.
CI is a different environment from local: headless, no human input, and often running in parallel. This episode covers proven integration patterns for GitHub Actions, GitLab CI, Jenkins, and Azure Pipelines, including how to capture test artifacts and run matrices for many browsers at once.
GitHub Actions is the easiest option because Playwright provides an official action:
name: End-to-End Tests
on:
push:
branches: [main, staging]
pull_request:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: actions/install-playwright@v1
with:
browsers: chromium,firefox,webkit
- run: npm ci
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-artifacts
path: test-results/
retention-days: 7actions/install-playwright@v1 installs the browser binaries with automatic caching. upload-artifact only runs on failure (if: failure()) to store test-results — traces and screenshots are available for review after the pipeline goes red.
For tests that need the application running, use webServer in the Playwright configuration — CI will wait for the server to be ready before running tests:
export default defineConfig({
webServer: {
command: 'npm run start',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
});webServer automatically launches the application, waits for the URL to be ready, then closes it after the suite finishes. With this, CI doesn't need to manage the server process manually.
GitLab CI uses the official Playwright Docker image, which already contains all browser dependencies:
stages:
- test
e2e:
stage: test
image: mcr.microsoft.com/playwright:v1.53.0
script:
- npm ci
- npx playwright test
artifacts:
when: always
paths:
- playwright-report/
- test-results/
expire_in: 7 daysmcr.microsoft.com/playwright:v1.53.0 is the official image containing Node.js, browsers, and system dependencies. GitLab stores artifacts with artifacts.when: always so the report is available even when tests succeed.
In Jenkins, the same pattern is written as a pipeline file: npx playwright install --with-deps then npx playwright test, with artifacts archived via archiveArtifacts. Azure Pipelines uses similar steps with the PublishTestResults task or its built-in artifact publishing mechanism.
CI has no display, so tests must run headless. This is already Playwright's default:
npx playwright testBy default Playwright runs headless in CI and headed locally when using --headed. To ensure consistency, set headless: true explicitly in the CI configuration, or just leave the correct default.
Headed mode in CI is useful for temporary debugging — for example, when checking behavior that only appears with a GPU. But for normal flows, headless is faster and uses fewer resources.
Enable artifacts selectively in CI so storage stays efficient:
export default defineConfig({
retries: process.env.CI ? 2 : 0,
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'on-first-retry',
},
});trace: 'on-first-retry' produces a trace when a test fails on the first attempt and passes on a retry — capturing flakiness that's usually hard to reproduce. Videos and screenshots are only kept for failed tests.
After the pipeline finishes, download the artifacts and open the report with:
npx playwright show-report playwright-report/npx playwright show-report playwright-report/ displays the report downloaded from CI. This report contains the trace viewer, screenshots, and videos for every failed test — complete information for debugging without re-running anything.
Playwright runs tests in parallel by default — multiple workers use multiple processes at once. Set the worker count in the configuration or CI:
npx playwright test --workers=4--workers=4 limits execution to 4 parallel processes. In CI, adjust it to the runner's resources — too many workers actually slows things down because they compete for CPU and memory.
With GitHub Actions matrices, each browser combination becomes a separate job that can run on a different runner:
strategy:
matrix:
browser: [chromium, firefox, webkit]
steps:
- run: npx playwright test --project=${{ matrix.browser }}--project=${{ matrix.browser }} filters execution to one project per job. A matrix gives resource isolation between browsers and enables clearer per-browser reports.
Episode 14 sent your suite into the production pipeline: GitHub Actions with the official action and artifact upload, GitLab CI with the official Docker image, Jenkins with archiving, and Azure Pipelines — all with the same principles: headless runs, selective failure artifacts, and matrix runs to broaden browser coverage.
Key takeaways:
webServer makes CI launch and wait for the application automatically.In the next episode we'll discuss speed and reliability optimization — optimizing runtime and parallelism, reusing contexts and fixtures with selective retries, reducing flaky tests with stable locators, and using test.fixme and test.skip strategically.