CI/CD Integration
CI/CD Integration
This guide covers running Stepwright scripts in CI/CD pipelines, including GitHub Actions, GitLab CI, and Jenkins.
Prerequisites
- Scripts configured for headless mode
- Artifacts directory accessible for upload
- Environment variables for secrets
GitHub Actions
Basic Workflow
name: Automation Tests
on: push: branches: [main] pull_request: branches: [main] schedule: - cron: '0 */6 * * *' # Every 6 hours
jobs: test: runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm'
- name: Install dependencies run: npm ci
- name: Install Playwright browsers run: npx playwright install chromium --with-deps
- name: Run automation scripts run: npx stepwright run ./scripts/main.ts --json ./results.json env: HEADLESS: 'true'
- name: Upload results if: always() uses: actions/upload-artifact@v4 with: name: results path: results.json
- name: Upload failure artifacts if: failure() uses: actions/upload-artifact@v4 with: name: artifacts path: .stepwright/artifacts/With Fixwright Auto-Fix
name: Automation with Auto-Fix
on: push: branches: [main] workflow_dispatch:
jobs: test: runs-on: ubuntu-latest outputs: failed: ${{ steps.run.outputs.failed }}
steps: - uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm'
- run: npm ci - run: npx playwright install chromium --with-deps
- name: Run automation id: run run: | npx stepwright run ./scripts/main.ts --json ./results.json || echo "failed=true" >> $GITHUB_OUTPUT continue-on-error: true
- name: Save failure case if: steps.run.outputs.failed == 'true' run: npx tsx scripts/generate-failure-case.ts
- name: Upload failure case if: steps.run.outputs.failed == 'true' uses: actions/upload-artifact@v4 with: name: failure-case path: failure-cases/
fix: needs: test if: needs.test.outputs.failed == 'true' runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm'
- run: npm ci
- name: Download failure case uses: actions/download-artifact@v4 with: name: failure-case path: failure-cases/
- name: Run Fixwright run: npx tsx scripts/fix-failures.ts env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Matrix Testing
Run scripts across multiple configurations:
jobs: test: runs-on: ubuntu-latest strategy: matrix: browser: [chromium, firefox, webkit] script: [login, checkout, search]
steps: - uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: node-version: '20'
- run: npm ci - run: npx playwright install ${{ matrix.browser }} --with-deps
- name: Run ${{ matrix.script }} on ${{ matrix.browser }} run: | npx stepwright run ./scripts/${{ matrix.script }}.ts \ --browser ${{ matrix.browser }} \ --json ./results-${{ matrix.browser }}-${{ matrix.script }}.jsonGitLab CI
Basic Pipeline
stages: - test - fix
variables: NODE_VERSION: "20"
automation: stage: test image: mcr.microsoft.com/playwright:v1.40.0-jammy script: - npm ci - npx stepwright run ./scripts/main.ts --json ./results.json artifacts: when: always paths: - results.json - .stepwright/artifacts/ expire_in: 1 week rules: - if: $CI_PIPELINE_SOURCE == "schedule" - if: $CI_COMMIT_BRANCH == "main"
fix-failures: stage: fix image: node:20 needs: - job: automation artifacts: true script: - npm ci - npx tsx scripts/fix-failures.ts variables: ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY GITHUB_TOKEN: $GITHUB_TOKEN rules: - if: $CI_JOB_STATUS == "failed" when: on_failureJenkins
Declarative Pipeline
pipeline { agent { docker { image 'mcr.microsoft.com/playwright:v1.40.0-jammy' } }
environment { NODE_OPTIONS = '--max-old-space-size=4096' }
stages { stage('Install') { steps { sh 'npm ci' } }
stage('Run Automation') { steps { sh 'npx stepwright run ./scripts/main.ts --json ./results.json' } post { always { archiveArtifacts artifacts: 'results.json', fingerprint: true } failure { archiveArtifacts artifacts: '.stepwright/artifacts/**/*' } } }
stage('Fix Failures') { when { expression { currentBuild.result == 'FAILURE' } } steps { withCredentials([ string(credentialsId: 'anthropic-api-key', variable: 'ANTHROPIC_API_KEY'), string(credentialsId: 'github-token', variable: 'GITHUB_TOKEN') ]) { sh 'npx tsx scripts/fix-failures.ts' } } } }
post { always { cleanWs() } }}Environment Configuration
Script Configuration
Detect CI environment and configure appropriately:
import { Stepwright } from '@korvol/stepwright';
const isCI = process.env.CI === 'true';
const script = Stepwright.create('Main Flow') .config({ headless: isCI || process.env.HEADLESS === 'true', screenshotOnFailure: true, domOnFailure: true, video: isCI ? { enabled: true, dir: './videos' } : undefined, defaultTimeout: isCI ? 60000 : 30000, });Environment Variables
env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BASE_URL: ${{ vars.BASE_URL }}variables: ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY # From CI/CD settings BASE_URL: "https://staging.example.com"withCredentials([ string(credentialsId: 'anthropic-key', variable: 'ANTHROPIC_API_KEY')]) { sh 'npx stepwright run ./scripts/main.ts'}Handling Failures
Exit Codes
Stepwright CLI uses standard exit codes:
0- Success1- Script failed2- Error (syntax, import, etc.)
Use in conditionals:
npx stepwright run ./scripts/main.ts || { echo "Script failed, generating failure case" npx tsx scripts/generate-failure-case.ts}Notification Integration
import { Stepwright, JSONReporter } from '@korvol/stepwright';
const script = Stepwright.create('With Notifications') .reporter(new JSONReporter({ outputPath: './results.json' }));
// After runconst result = await script.run();
if (!result.success) { // Send to Slack await fetch(process.env.SLACK_WEBHOOK!, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: `Automation failed: ${result.failedStep?.name}`, attachments: [{ color: 'danger', fields: [{ title: 'Error', value: result.failedStep?.error.message, }], }], }), });}Docker Support
Custom Dockerfile
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
WORKDIR /app
COPY package*.json ./RUN npm ci
COPY . .
CMD ["npx", "stepwright", "run", "./scripts/main.ts"]Docker Compose
services: automation: build: . environment: - HEADLESS=true volumes: - ./results:/app/results - ./artifacts:/app/.stepwright/artifactsScheduling
Cron Schedules
on: schedule: - cron: '0 */6 * * *' # Every 6 hours - cron: '0 9 * * 1-5' # 9 AM on weekdaysConfigure in GitLab UI: CI/CD → Schedules
Best Practices
1. Always Upload Artifacts
- name: Upload artifacts if: always() # Even on failure uses: actions/upload-artifact@v4 with: name: artifacts path: | results.json .stepwright/artifacts/ videos/2. Use Retries for Flaky Tests
- name: Run with retries uses: nick-fields/retry@v2 with: timeout_minutes: 10 max_attempts: 3 command: npx stepwright run ./scripts/main.ts3. Parallel Execution
strategy: matrix: shard: [1, 2, 3, 4] fail-fast: false
steps: - run: npx stepwright run ./scripts/main.ts --shard ${{ matrix.shard }}/44. Cache Dependencies
- uses: actions/cache@v4 with: path: | ~/.npm ~/.cache/ms-playwright key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}Next Steps
- Debugging Failures - Debug CI failures
- Best Practices - Production recommendations
- Fixwright PR Creation - Auto-create fix PRs