Introduction
Running Playwright tests in GitHub Actions is one of the most popular ways to automate regression testing. However, downloading Node.js packages and Playwright browser binaries during every workflow run can significantly increase pipeline execution time.
This is where Playwright GitHub Actions Caching becomes important.
By caching npm dependencies and Playwright browser binaries, teams can reduce workflow execution time, lower infrastructure costs, and deliver faster feedback to developers.
In this guide, you’ll learn how to implement Playwright GitHub Actions Caching, cache browser binaries, optimize workflows, upload reports as artifacts, and build enterprise-ready CI/CD pipelines using GitHub Actions.
Why Caching Matters in GitHub Actions
Without caching, every GitHub Actions workflow typically performs the following tasks:
- Downloads Node.js
- Installs npm packages
- Downloads Playwright browsers
- Installs project dependencies
- Runs tests
Downloading the same dependencies repeatedly wastes time and network bandwidth.
Benefits of Caching
- Faster workflow execution
- Reduced network usage
- Lower CI/CD costs
- Better developer productivity
- More predictable pipeline duration
- Improved scalability
How Playwright Downloads Browsers and Dependencies
A Playwright project has two primary dependency groups:
1. Node.js Packages
Installed using:
npm install
These packages are stored in:
node_modules/
2. Browser Binaries
Installed using:
npx playwright install –with-deps
Browsers include:
- Chromium
- Firefox
- WebKit
These binaries are stored in Playwright’s browser cache directory and can be reused across workflow runs when cached appropriately.
Prerequisites (GitHub Repository, Node.js, Playwright, GitHub Actions)
Before implementing Playwright GitHub Actions Caching, ensure you have:
- GitHub repository
- Node.js project
- Playwright installed
- GitHub Actions enabled
- TypeScript or JavaScript project
- package.json
- playwright.config.ts
Typical project structure:
playwright-project
│
├── tests
├── pages
├── utils
├── playwright.config.ts
├── package.json
└── .github
└── workflows
└── playwright.yml
Creating a Basic GitHub Actions Workflow
A simple Playwright workflow looks like this:
name: Playwright Tests
on:
push:
branches:
– main
jobs:
test:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-node@v4
with:
node-version: 20
– run: npm ci
– run: npx playwright install –with-deps
– run: npx playwright test
Step-by-Step Explanation
- Checks out the repository.
- Installs Node.js.
- Installs npm packages.
- Downloads Playwright browsers.
- Executes the test suite.
This workflow works correctly but downloads dependencies on every run.
Caching node_modules and npm Dependencies
GitHub Actions supports dependency caching through actions/setup-node.
– uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
Why Use It?
GitHub Actions caches downloaded npm packages, allowing future workflow runs to restore them instead of downloading everything again.
For most npm projects, using cache: npm is the recommended approach because it is simple and maintained by GitHub.
Using actions/cache
For more control, you can use actions/cache.
– uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles(‘package-lock.json’) }}
restore-keys: |
npm-${{ runner.os }}-
Explanation
- path – Directory to cache.
- key – Unique identifier for the cache.
- restore-keys – Allows partial cache matches if an exact key is unavailable.
Caching Playwright Browser Binaries
Playwright browser downloads are often the largest part of the setup process.
Cache the browser directory:
– uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles(‘package-lock.json’) }}
restore-keys: |
playwright-${{ runner.os }}-
After restoring the cache:
– run: npx playwright install –with-deps
If the cache already contains the required browser versions, Playwright reuses them instead of downloading them again.
Cache Keys, Restore Keys, and Cache Invalidation
Choosing the right cache key is essential.
Example
key: playwright-${{ runner.os }}-${{ hashFiles(‘package-lock.json’) }}
Whenever package-lock.json changes, GitHub creates a new cache.
Restore Keys
restore-keys: |
playwright-${{ runner.os }}-
If no exact cache exists, GitHub searches for the closest matching cache.
Cache Lifecycle
Workflow Starts
│
▼
Cache Exists?
│ │
Yes No
│ │
▼ ▼
Restore Download
│ │
└──────┬─────┘
▼
Execute Tests
│
▼
Save Updated Cache
Avoid overly broad cache keys, as stale caches can cause inconsistent behavior.
Running Playwright Tests Efficiently in CI
Configure Playwright for CI environments.
import { defineConfig } from ‘@playwright/test’;
export default defineConfig({
workers: process.env.CI ? 2 : undefined,
retries: process.env.CI ? 2 : 0,
reporter: [[‘html’]]
});
Why These Settings?
- Limits worker count on CI to avoid resource contention.
- Enables retries only in CI.
- Generates HTML reports automatically.
Uploading HTML Reports, Screenshots, Videos, and Trace Files as Artifacts
Publishing artifacts makes debugging easier.
– uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
Upload screenshots and traces:
– uses: actions/upload-artifact@v4
if: failure()
with:
name: failure-artifacts
path: |
test-results/
playwright-report/
Benefits
- Easier debugging
- Historical execution records
- Trace Viewer support
- Downloadable reports
Performance Optimization Tips
Use npm ci
npm ci
It provides faster and more predictable installations for CI than npm install.
Cache Browser Downloads
Avoid downloading Chromium, Firefox, and WebKit for every run.
Use Matrix Builds
strategy:
matrix:
browser:
– chromium
– firefox
This allows multiple browser configurations to run in parallel.
Run Tests in Parallel
Playwright automatically supports parallel execution.
workers: 4
Adjust the worker count based on the resources available in your GitHub-hosted or self-hosted runners.
Enterprise CI/CD Best Practices
For enterprise-grade Playwright GitHub Actions Caching, follow these practices:
- Cache npm packages.
- Cache Playwright browser binaries.
- Use npm ci in CI.
- Keep Node.js versions consistent.
- Store secrets in GitHub Secrets.
- Upload reports as artifacts.
- Archive screenshots and traces.
- Use matrix builds for browser coverage.
- Separate smoke and regression pipelines.
- Review cache hit rates and update strategies when dependencies change.
Common Caching Issues and Troubleshooting
| Problem | Solution |
| Cache not restored | Verify the cache key and path |
| Browser downloads every run | Cache the Playwright browser directory |
| Cache too large | Cache only required directories |
| Stale dependencies | Invalidate the cache when lock files change |
| Slow workflows | Use npm ci and dependency caching |
| Missing reports | Upload artifacts with if: always() |
Troubleshooting Flow
Slow Workflow
│
▼
Cache Hit?
│
▼
Dependency Cache
│
▼
Browser Cache
│
▼
Artifacts
│
▼
Optimized Pipeline
Real-Time Enterprise GitHub Actions Workflow Example
The following workflow combines dependency caching, browser caching, Playwright execution, and artifact uploads.
name: Playwright CI
on:
push:
branches:
– main
jobs:
test:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
– uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles(‘package-lock.json’) }}
restore-keys: |
playwright-${{ runner.os }}-
– run: npm ci
– run: npx playwright install –with-deps
– run: npx playwright test
– uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
Workflow Overview
Developer Push
│
▼
GitHub Actions
│
▼
Restore npm Cache
│
▼
Restore Browser Cache
│
▼
Install Dependencies
│
▼
Run Playwright Tests
│
▼
Generate HTML Report
│
▼
Upload Artifacts
Performance Comparison
| Without Caching | With Caching |
| Downloads dependencies every run | Reuses cached packages when available |
| Downloads browsers each run | Reuses cached browser binaries |
| Longer setup time | Faster setup time |
| Higher network usage | Lower network usage |
| Less predictable pipeline duration | More consistent execution times |
The exact time savings depend on project size, dependency changes, and runner performance, but caching commonly reduces setup time significantly.
Playwright GitHub Actions Caching Interview Questions
- What is GitHub Actions caching?
- Why is caching important in CI/CD?
- How does Playwright download browser binaries?
- What is actions/cache?
- What is actions/setup-node?
- How do you cache npm dependencies?
- How do you cache Playwright browsers?
- What is a cache key?
- What are restore keys?
- How does cache invalidation work?
- Why use npm ci instead of npm install?
- What is a matrix build?
- How do you upload HTML reports?
- How do you upload screenshots?
- How do you upload trace files?
- How do you configure retries for CI?
- What are GitHub Secrets?
- How do you secure credentials in GitHub Actions?
- How do you optimize Playwright workflows?
- Why separate smoke and regression pipelines?
- What causes cache misses?
- How do you troubleshoot slow workflows?
- How do you improve Playwright CI/CD performance?
- How do you debug GitHub Actions failures?
- How would you explain your Playwright GitHub Actions pipeline in an interview?
FAQs
What is Playwright GitHub Actions Caching?
It is the practice of storing reusable dependencies—such as npm packages and Playwright browser binaries—between workflow runs to reduce setup time and improve CI/CD performance.
Should I cache node_modules?
In most cases, it is better to use actions/setup-node with cache: npm or cache the npm package cache rather than caching the entire node_modules directory. This approach is generally more reliable across workflow runs.
Why are browsers downloaded again?
This usually happens when the browser cache directory is not cached, the cache key changes, or Playwright requires a different browser version after an update.
How do I invalidate a cache?
Include files such as package-lock.json in the cache key. When those files change, GitHub automatically creates a new cache.
Should I upload Playwright reports?
Yes. Upload HTML reports, screenshots, videos, and trace files as workflow artifacts to simplify debugging and post-run analysis.
Is caching always beneficial?
Caching is most effective for projects with stable dependencies. If dependencies change frequently, cache misses may reduce the benefit, but the overall approach still improves many CI workflows.
