How can I integrate Playwright with CI/CD pipelines?
Integrating Playwright with CI/CD pipelines is essential for automated testing, web scraping, and quality assurance workflows. This comprehensive guide covers setup, configuration, and best practices for popular CI/CD platforms including GitHub Actions, Jenkins, GitLab CI, and Azure DevOps.
Understanding Playwright in CI/CD Context
Playwright is particularly well-suited for CI/CD pipelines due to its: - Cross-browser support (Chromium, Firefox, WebKit) - Headless execution capabilities - Built-in waiting mechanisms - Comprehensive debugging tools - Docker support for containerized environments
GitHub Actions Integration
Basic GitHub Actions Workflow
Create a .github/workflows/playwright.yml
file in your repository:
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
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: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
Advanced GitHub Actions Configuration
For more complex scenarios with multiple environments and parallel execution:
name: Cross-Browser Testing
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
project: [chromium, firefox, webkit]
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Install Playwright
run: npx playwright install --with-deps ${{ matrix.project }}
- name: Run Playwright tests
run: npx playwright test --project=${{ matrix.project }} --shard=${{ matrix.shard }}/${{ strategy.job-total }}
- name: Upload blob report to GitHub Actions Artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: blob-report-${{ matrix.project }}-${{ matrix.shard }}
path: blob-report
retention-days: 1
merge-reports:
if: always()
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@v4
with:
path: all-blob-reports
pattern: blob-report-*
merge-multiple: true
- name: Merge into HTML Report
run: npx playwright merge-reports --reporter html ./all-blob-reports
- name: Upload HTML report
uses: actions/upload-artifact@v4
with:
name: html-report--attempt-${{ github.run_attempt }}
path: playwright-report
retention-days: 14
Jenkins Integration
Jenkins Pipeline Configuration
Create a Jenkinsfile
for Jenkins pipeline integration:
pipeline {
agent any
tools {
nodejs "NodeJS-18"
}
environment {
CI = 'true'
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = '1'
}
stages {
stage('Install Dependencies') {
steps {
sh 'npm ci'
}
}
stage('Install Playwright') {
steps {
sh 'npx playwright install --with-deps'
}
}
stage('Run Tests') {
steps {
sh 'npx playwright test'
}
post {
always {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'playwright-report',
reportFiles: 'index.html',
reportName: 'Playwright Report'
])
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'playwright-report/**/*', fingerprint: true
junit 'test-results/junit.xml'
}
}
}
Jenkins with Docker
For containerized Jenkins builds:
pipeline {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.40.0-focal'
args '-u root:root'
}
}
stages {
stage('Install Dependencies') {
steps {
sh 'npm ci'
}
}
stage('Run Playwright Tests') {
steps {
sh 'npx playwright test'
}
}
}
}
GitLab CI Integration
GitLab CI Configuration
Create a .gitlab-ci.yml
file:
image: node:18
stages:
- test
- report
variables:
CI: "true"
cache:
paths:
- node_modules/
before_script:
- npm ci
- npx playwright install --with-deps
playwright-tests:
stage: test
script:
- npx playwright test
artifacts:
when: always
paths:
- playwright-report/
- test-results/
reports:
junit: test-results/junit.xml
expire_in: 1 week
pages:
stage: report
dependencies:
- playwright-tests
script:
- mkdir public
- cp -r playwright-report/* public/
artifacts:
paths:
- public
only:
- main
GitLab CI with Docker
Using the official Playwright Docker image:
image: mcr.microsoft.com/playwright:v1.40.0-focal
stages:
- test
variables:
CI: "true"
playwright-tests:
stage: test
before_script:
- npm ci
script:
- npx playwright test
artifacts:
when: always
paths:
- playwright-report/
- test-results/
expire_in: 1 week
Azure DevOps Integration
Azure Pipelines Configuration
Create an azure-pipelines.yml
file:
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
CI: true
steps:
- task: NodeTool@0
inputs:
versionSpec: '18.x'
displayName: 'Install Node.js'
- script: |
npm ci
displayName: 'Install dependencies'
- script: |
npx playwright install --with-deps
displayName: 'Install Playwright browsers'
- script: |
npx playwright test
displayName: 'Run Playwright tests'
- task: PublishTestResults@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'test-results/junit.xml'
failTaskOnFailedTests: true
condition: succeededOrFailed()
displayName: 'Publish test results'
- task: PublishHtmlReport@1
inputs:
reportDir: 'playwright-report'
tabName: 'Playwright Report'
condition: succeededOrFailed()
displayName: 'Publish HTML report'
Docker Integration
Dockerfile for Playwright
Create a Dockerfile
for containerized Playwright execution:
FROM mcr.microsoft.com/playwright:v1.40.0-focal
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npx", "playwright", "test"]
Docker Compose for Development
version: '3.8'
services:
playwright:
build: .
volumes:
- ./playwright-report:/app/playwright-report
- ./test-results:/app/test-results
environment:
- CI=true
Configuration Best Practices
Playwright Configuration for CI
Create a playwright.config.js
optimized for CI environments:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [
['html'],
['junit', { outputFile: 'test-results/junit.xml' }],
['github'] // GitHub Actions integration
],
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
webServer: {
command: 'npm run start',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
});
Environment Variables
Set up environment-specific configurations:
// In your test files
const config = {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
timeout: process.env.CI ? 30000 : 10000,
retries: process.env.CI ? 2 : 0,
};
Advanced CI/CD Patterns
Conditional Test Execution
# GitHub Actions example
- name: Run smoke tests
if: github.event_name == 'pull_request'
run: npx playwright test --grep "@smoke"
- name: Run full test suite
if: github.ref == 'refs/heads/main'
run: npx playwright test
Parallel Execution with Sharding
// playwright.config.js
export default defineConfig({
projects: [
{
name: 'setup',
testMatch: /.*\.setup\.js/,
},
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
dependencies: ['setup'],
},
],
// Enable sharding
shard: process.env.CI ? { current: 1, total: 4 } : undefined,
});
Test Result Notifications
# Slack notification example
- name: Notify Slack
if: failure()
uses: 8398a7/action-slack@v3
with:
status: failure
text: "Playwright tests failed on ${{ github.ref }}"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Performance Optimization
Caching Strategies
# Cache Playwright browsers
- name: Cache Playwright browsers
uses: actions/cache@v3
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
Resource Management
// Optimize for CI environments
export default defineConfig({
workers: process.env.CI ? 1 : undefined,
use: {
// Reduce resource usage
launchOptions: {
args: ['--no-sandbox', '--disable-dev-shm-usage'],
},
},
});
Troubleshooting Common Issues
Browser Installation Problems
# Install system dependencies
sudo apt-get update
sudo apt-get install -y libnss3 libnspr4 libdbus-1-3 libatk1.0-0 libdrm2 libxkbcommon0 libgtk-3-0 libatspi2.0-0
# Install Playwright browsers
npx playwright install --with-deps
Memory Issues
# Increase memory limit
- name: Run tests with increased memory
run: NODE_OPTIONS="--max-old-space-size=4096" npx playwright test
Security Considerations
Secrets Management
# GitHub Actions secrets
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Network Security
// Restrict network access
export default defineConfig({
use: {
extraHTTPHeaders: {
'Authorization': `Bearer ${process.env.API_TOKEN}`,
},
},
});
Monitoring and Reporting
Test Analytics
// Custom reporter for analytics
class CustomReporter {
onTestEnd(test, result) {
// Send metrics to monitoring service
console.log(`Test ${test.title}: ${result.status}`);
}
}
export default defineConfig({
reporter: [['html'], [CustomReporter]],
});
Integrating Playwright with CI/CD pipelines enables automated testing, continuous quality assurance, and reliable web scraping workflows. By following these configurations and best practices, you can create robust, scalable automation pipelines that ensure your applications maintain high quality standards throughout the development lifecycle.
For more advanced automation scenarios, consider exploring how to handle authentication in Puppeteer for comparison with Playwright's authentication handling, or learn about using Puppeteer with Docker to understand containerization patterns that also apply to Playwright deployments.