Manuals / Playwright with Python / Ch 34

Part 5 · CI/CD & ReportingAdvanced50 min read

25. CI/CD Integration

Playwright with Python · 244 pages source format

GitHub Actions workflow setup A GitHub Actions workflow is a YAML file living in .github/workflows/ that defines when tests run (e.g., on every pull request) and what steps to execute. # .github/workflows/playwright.yml name: Playwright Tests on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@

What you'll learn

  • GitHub Actions workflow setup
  • Jenkins pipeline basics
  • Running headless in CI

GitHub Actions workflow setup

A GitHub Actions workflow is a YAML file living in .github/workflows/ that defines when tests run (e.g., on every pull request) and what steps to execute.

push:

branches: [main]

pull_request:

branches: [main]

test:

runs-on: ubuntu-latest

with:

python-version: '3.11'

- name: Install dependencies

- name: Run tests

What it does: Defines which events cause the workflow to run.

Types/params:

Pointers: Running on pull_request is the most common setup for catching

regressions before merge; schedule is useful for a nightly full-regression run separate from a fast pull_request smoke-test run.

What it does: Installs browser binaries plus the OS-level system dependencies (fonts, libraries) those browsers need to actually run on a fresh CI machine.

Types/params: No required params; --with-deps is the key flag for CI environments specifically.

Pointers: On a fresh CI runner (unlike your local dev machine), the OS-level dependencies genuinely aren't present — skipping --with-deps is a very common cause of "works locally, fails in CI" browser launch errors.

  • push (dict, optional) — runs on pushes to specified branches
  • pull_request (dict, optional) — runs when a PR is opened/updated against specified branches
  • schedule (list, optional) — cron-based scheduled runs, e.g. nightly regression suites
Run / study this snippet
run: |
Interactive study board
GitHub Actions workflow setupDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

Jenkins pipeline basics

Jenkins uses a Jenkinsfile (Groovy-based) to define pipeline stages, more common in traditional enterprise environments than GitHub Actions.

// Jenkinsfile

pipeline {

agent any

stages {

steps {

sh 'pip install -r requirements.txt'

sh 'playwright install --with-deps'

}

}

steps {

sh 'pytest --browser chromium --junitxml=results.xml'

}

}

}

post {

always {

junit 'results.xml'

}

}

}

pipeline { agent ... stages { ... } post { ... } } (Jenkinsfile structure)

What it does: Defines the overall pipeline: where it runs (agent), what steps execute

in order (stages), and cleanup/reporting actions that always run afterward (post).

Types/params:

plugin calls)

Pointers: --junitxml=results.xml produces a report format Jenkins natively

understands and can render as pass/fail trends over time via the junit post-step — this is Jenkins' equivalent of GitHub Actions' built-in test summary UI.

  • agent — any (run on any available Jenkins worker) or a specific labeled machine/Docker image
  • stages — ordered list of named stages, each with steps (shell commands or
  • post { always {...} } — actions that run regardless of pass/fail, commonly used to publish test result reports
Run / study this snippet
stage('Install') {
Interactive study board
Jenkins pipeline basicsDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

Running headless in CI

Pointers: CI runners have no display server, so headless isn't optional — attempting to run headed (--headed) on a typical CI machine will fail outright unless a virtual display (like xvfb) is specifically configured, which is rarely worth the added complexity when headless works and is faster anyway.

Run / study this snippet
# pytest-playwright defaults to headless=True already, but explicit is safer:
Interactive study board
Running headless in CIDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

Checklist