Run Playwright Tests in GitHub Actions: CI Workflow, Secrets, Sharding and Reports

Automation pays off when it runs on every change. In this lesson you will run your Playwright TypeScript suite in GitHub Actions, handle secrets, read reports and traces from CI, shard across parallel jobs, and schedule nightly regression runs.

Advertisement

๐Ÿ“– What You’ll Learn: the Playwright workflow YAML step by step, CI-friendly config, secrets and variables, downloading reports and traces, sharding with a matrix and merged report, running in the official Docker image, nightly and manual runs, and a CI checklist.


๐Ÿš€ Why Run Playwright in CI?

Tests that only run on your laptop protect nobody. Continuous Integration (CI) runs your suite automatically on every push and pull request, so broken code is caught before it is merged. GitHub Actions is the most common choice for projects on GitHub, and Playwright supports it out of the box.

New to GitHub Actions itself? Start with the GitHub Actions complete roadmap and GitHub Actions fundamentals for beginners.


๐Ÿงพ Step 1: The Basic Workflow

If you answered Yes to “Add a GitHub Actions workflow?” during installation, you already have this file. Otherwise create .github/workflows/playwright.yml:

name: Playwright Tests
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: lts/*

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

What each step does:

StepPurpose
actions/checkoutDownloads your repository
actions/setup-nodeInstalls Node.js
npm ciInstalls the exact versions from package-lock.json
npx playwright install --with-depsDownloads browsers and Linux system libraries
npx playwright testRuns the suite
upload-artifactSaves the HTML report (with traces and screenshots) even when tests fail

โš ๏ธ Common mistake: Always commit package-lock.json. npm ci fails without it, and it guarantees CI uses the same Playwright version as your machine.


โš™๏ธ Step 2: CI-Friendly Config

The default config already reacts to process.env.CI, which GitHub sets automatically:

export default defineConfig({
  forbidOnly: !!process.env.CI,          // fail if test.only was committed
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 2 : undefined,
  reporter: process.env.CI
    ? [['dot'], ['github'], ['html', { open: 'never' }]]
    : [['list'], ['html', { open: 'on-failure' }]],
  use: {
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
});

The github reporter adds annotations to the pull request, pointing at the exact failing lines.


๐Ÿ” Step 3: Secrets and Environment Variables

Never commit passwords or tokens. Add them under Settings, Secrets and variables, Actions in your repository, then pass them to the job:

      - name: Run Playwright tests
        run: npx playwright test
        env:
          BASE_URL: ${{ vars.BASE_URL }}
          TEST_USER: ${{ secrets.TEST_USER }}
          TEST_PASSWORD: ${{ secrets.TEST_PASSWORD }}

Read them in your config and tests with process.env.BASE_URL (environment variables). GitHub masks secret values in logs.


๐Ÿ“ฅ Step 4: Read the Results

  1. Open the Actions tab and the workflow run.
  2. Failing tests appear as annotations in the summary and on the pull request.
  3. Download the playwright-report artifact, unzip it and run npx playwright show-report playwright-report.
  4. Open a failed test and its trace (Trace Viewer).

๐Ÿงฉ Step 5: Shard Across Parallel Jobs

For large suites, split tests across several machines with a matrix and merge the reports (parallel execution and sharding):

name: Playwright Tests (sharded)
on: [push, pull_request]

jobs:
  playwright-tests:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4]
        shardTotal: [4]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
      - run: npm ci
      - run: npx playwright install --with-deps
      - name: Run shard
        run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --reporter=blob
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: blob-report-${{ matrix.shardIndex }}
          path: blob-report
          retention-days: 1

  merge-reports:
    if: ${{ !cancelled() }}
    needs: [playwright-tests]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
      - run: npm ci
      - uses: actions/download-artifact@v4
        with:
          path: all-blob-reports
          pattern: blob-report-*
          merge-multiple: true
      - name: Merge into one HTML report
        run: npx playwright merge-reports --reporter html ./all-blob-reports
      - uses: actions/upload-artifact@v4
        with:
          name: html-report--attempt-${{ github.run_attempt }}
          path: playwright-report
          retention-days: 14

๐Ÿณ Option: Run Inside the Official Playwright Docker Image

The official image already contains browsers and system libraries, which also gives consistent screenshots for visual tests:

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: mcr.microsoft.com/playwright:v1.xx.x-noble   # use the SAME version as @playwright/test in package.json
      options: --user 1001
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: lts/*
      - run: npm ci
      - run: npx playwright test

๐Ÿ“ Note: The image tag must match your installed @playwright/test version, otherwise Playwright looks for browser builds that are not in the image. More in Playwright with Docker and Kubernetes.


โฐ Nightly and Manual Runs

Run the full cross-browser regression every night and allow manual runs from the Actions tab:

on:
  schedule:
    - cron: '30 20 * * *'      # 20:30 UTC = 02:00 IST
  workflow_dispatch:
    inputs:
      grep:
        description: 'Tag to run, e.g. @smoke'
        required: false
        default: ''

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      # ...checkout, setup-node, npm ci, install browsers...
      - run: npx playwright test --grep "${{ github.event.inputs.grep }}"

Combine with tags: @smoke on every pull request, the full suite nightly.


โœ… CI Checklist

  • package-lock.json committed, npm ci in CI.
  • Browsers installed with --with-deps (or the official Docker image).
  • forbidOnly, retries and trace: 'on-first-retry' enabled for CI.
  • HTML report uploaded with if: !cancelled() so you get it when tests fail.
  • Secrets in GitHub Secrets, never in code.
  • Pull-request gate fast (smoke or Chromium only); full matrix nightly.

๐Ÿ“ Assignment

  1. Push your Sauce Demo project to a GitHub repository with the basic workflow and watch it run in the Actions tab.
  2. Break a test on purpose, push, and find the failure annotation and the trace in the downloaded report.
  3. Move the base URL into a repository variable and a password into a secret, and read them in the config.
  4. Add the github and dot reporters for CI only.
  5. Convert the workflow to 2 shards with a merged HTML report.
  6. Add a nightly schedule and a manual workflow_dispatch with a grep input.
  7. Bonus: run the job inside the official Playwright Docker image matching your version.

โ“ FAQ

๐Ÿค” How do I run Playwright tests in GitHub Actions?

Add a workflow that checks out the code, sets up Node.js, runs npm ci, npx playwright install --with-deps and npx playwright test, then uploads playwright-report as an artifact.

๐Ÿค” How do I see the Playwright report from GitHub Actions?

Download the playwright-report artifact from the workflow run, unzip it and run npx playwright show-report <folder>, or publish it to GitHub Pages.

๐Ÿค” How do I use secrets in Playwright GitHub Actions?

Store them in the repository’s Actions secrets and pass them as env values with ${{ secrets.NAME }}; read them with process.env.NAME.

๐Ÿค” How do I run Playwright tests in parallel on GitHub Actions?

Use a matrix with --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} and the blob reporter, then merge the blob reports in a final job.

๐Ÿค” Should I cache Playwright browsers in GitHub Actions?

Usually not. Restoring a large cache takes about as long as downloading browsers, and the system dependencies still need installing. The official Docker image is a faster alternative.


๐ŸŽฏ Next Steps

๐ŸŽฌ Watch the full Playwright tutorial series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

4 thoughts on “Run Playwright Tests in GitHub Actions: CI Workflow, Secrets, Sharding and Reports”

Leave a Comment