CI/CD Integration

Integrate the Playwright C# Agentic Framework into your continuous integration and deployment pipelines. This guide covers setup for popular CI/CD platforms.

GitHub Actions

Basic Workflow

Create .github/workflows/tests.yml:

name: E2E Tests

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '9.0.x'
      
      - name: Restore dependencies
        run: dotnet restore
      
      - name: Build solution
        run: dotnet build --no-restore
      
      - name: Install Playwright browsers
        run: |
          dotnet build ./Tests.E2E/Tests.E2E.csproj
          bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
      
      - name: Run tests
        run: |
          dotnet test ./Tests.E2E/Tests.E2E.csproj \
            --logger:"junit;LogFileName=junit.xml" \
            --results-directory ./allure-results \
            --no-build
        continue-on-error: true
      
      - name: Generate Allure report
        if: always()
        run: |
          npm install -g allure-commandline
          allure generate --clean ./allure-results -o ./allure-report
      
      - name: Upload Allure report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: allure-report
          path: ./allure-report
          retention-days: 30

With Healing

Add healing step after test failures:

      - name: Run tests
        id: tests
        run: |
          dotnet test ./Tests.E2E/Tests.E2E.csproj \
            --logger:"junit;LogFileName=junit.xml" \
            --results-directory ./allure-results
        continue-on-error: true
      
      - name: Learn selectors (if tests passed)
        if: steps.tests.outcome == 'success'
        run: |
          dotnet run --project ./Agents/Agents.csproj -- learn \
            --test ./Tests.E2E/Tests.E2E.csproj \
            --out  ./agents/selectors.registry.json
      
      - name: Heal tests (if tests failed)
        if: steps.tests.outcome == 'failure'
        run: |
          dotnet run --project ./Agents/Agents.csproj -- heal \
            --test ./Tests.E2E/Tests.E2E.csproj
        continue-on-error: true
      
      - name: Re-run healed tests
        if: steps.tests.outcome == 'failure'
        run: |
          dotnet test ./Tests.E2E/Tests.E2E.csproj \
            --logger:"junit;LogFileName=junit.xml" \
            --results-directory ./allure-results

Matrix Strategy (Multiple Browsers)

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        browser: [chromium, firefox, webkit]
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '9.0.x'
      
      - name: Install Playwright browsers
        run: |
          dotnet build ./Tests.E2E/Tests.E2E.csproj
          bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps ${{ matrix.browser }}
      
      - name: Run tests
        env:
          BROWSER: ${{ matrix.browser }}
        run: |
          dotnet test ./Tests.E2E/Tests.E2E.csproj \
            --logger:"junit;LogFileName=junit-${{ matrix.browser }}.xml" \
            --results-directory ./allure-results

Azure DevOps

Pipeline YAML

Create azure-pipelines.yml:

trigger:
  branches:
    include:
      - main
      - develop

pool:
  vmImage: 'ubuntu-latest'

variables:
  dotnetVersion: '9.0.x'

stages:
  - stage: Test
    jobs:
      - job: E2ETests
        steps:
          - task: UseDotNet@2
            displayName: 'Use .NET SDK'
            inputs:
              version: '$(dotnetVersion)'
          
          - task: DotNetCoreCLI@2
            displayName: 'Restore dependencies'
            inputs:
              command: 'restore'
          
          - task: DotNetCoreCLI@2
            displayName: 'Build solution'
            inputs:
              command: 'build'
          
          - script: |
              dotnet build ./Tests.E2E/Tests.E2E.csproj
              bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
            displayName: 'Install Playwright browsers'
          
          - task: DotNetCoreCLI@2
            displayName: 'Run tests'
            inputs:
              command: 'test'
              projects: '**/Tests.E2E.csproj'
              arguments: '--logger:"junit;LogFileName=junit.xml" --results-directory ./allure-results'
            continueOnError: true
          
          - script: |
              npm install -g allure-commandline
              allure generate --clean ./allure-results -o ./allure-report
            displayName: 'Generate Allure report'
          
          - task: PublishTestResults@2
            displayName: 'Publish test results'
            inputs:
              testResultsFormat: 'JUnit'
              testResultsFiles: '**/junit.xml'
            condition: always()
          
          - task: PublishBuildArtifacts@1
            displayName: 'Publish Allure report'
            inputs:
              pathToPublish: './allure-report'
              artifactName: 'allure-report'
            condition: always()

Jenkins

Jenkinsfile

Create Jenkinsfile:

pipeline {
    agent any
    
    tools {
        dotnet 'dotnet-9.0'
    }
    
    environment {
        DOTNET_VERSION = '9.0.x'
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Restore') {
            steps {
                sh 'dotnet restore'
            }
        }
        
        stage('Build') {
            steps {
                sh 'dotnet build --no-restore'
            }
        }
        
        stage('Install Playwright') {
            steps {
                sh '''
                    dotnet build ./Tests.E2E/Tests.E2E.csproj
                    bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
                '''
            }
        }
        
        stage('Test') {
            steps {
                sh '''
                    dotnet test ./Tests.E2E/Tests.E2E.csproj \
                      --logger:"junit;LogFileName=junit.xml" \
                      --results-directory ./allure-results
                '''
            }
        }
        
        stage('Report') {
            steps {
                sh 'allure generate --clean ./allure-results -o ./allure-report'
            }
        }
    }
    
    post {
        always {
            allure([
                includeProperties: false,
                jdk: '',
                properties: [],
                reportBuildPolicy: 'ALWAYS',
                results: [[path: 'allure-results']]
            ])
            
            archiveArtifacts artifacts: 'allure-report/**', fingerprint: true
        }
    }
}

GitLab CI

.gitlab-ci.yml

image: mcr.microsoft.com/dotnet/sdk:9.0

variables:
  DOTNET_VERSION: "9.0.x"

stages:
  - test

e2e-tests:
  stage: test
  before_script:
    - dotnet restore
    - dotnet build
    - dotnet build ./Tests.E2E/Tests.E2E.csproj
    - bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
  script:
    - dotnet test ./Tests.E2E/Tests.E2E.csproj
      --logger:"junit;LogFileName=junit.xml"
      --results-directory ./allure-results
  artifacts:
    when: always
    paths:
      - allure-results/
      - allure-report/
    reports:
      junit: allure-results/junit.xml
    expire_in: 30 days
  after_script:
    - npm install -g allure-commandline || true
    - allure generate --clean ./allure-results -o ./allure-report || true

CircleCI

.circleci/config.yml

version: 2.1

jobs:
  test:
    docker:
      - image: mcr.microsoft.com/dotnet/sdk:9.0
    steps:
      - checkout
      - run:
          name: Restore dependencies
          command: dotnet restore
      - run:
          name: Build solution
          command: dotnet build
      - run:
          name: Install Playwright
          command: |
            dotnet build ./Tests.E2E/Tests.E2E.csproj
            bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium
      - run:
          name: Run tests
          command: |
            dotnet test ./Tests.E2E/Tests.E2E.csproj \
              --logger:"junit;LogFileName=junit.xml" \
              --results-directory ./allure-results
      - store_test_results:
          path: ./allure-results
      - store_artifacts:
          path: ./allure-results
          destination: test-results

workflows:
  version: 2
  test:
    jobs:
      - test

Environment Variables

Secure Configuration

Store sensitive values as secrets in your CI/CD platform:

GitHub Actions:

env:
  BASE_URL: ${{ secrets.BASE_URL }}
  USER_EMAIL: ${{ secrets.USER_EMAIL }}
  USER_PASSWORD: ${{ secrets.USER_PASSWORD }}

Azure DevOps:

variables:
  - group: 'test-credentials'

Jenkins:

environment {
    BASE_URL = credentials('base-url')
    USER_EMAIL = credentials('user-email')
    USER_PASSWORD = credentials('user-password')
}

Best Practices

1. Cache Dependencies

GitHub Actions:

- name: Cache .NET packages
  uses: actions/cache@v3
  with:
    path: ~/.nuget/packages
    key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}

2. Fail Fast on Critical Tests

- name: Run critical tests first
  run: |
    dotnet test ./Tests.E2E/Tests.E2E.csproj \
      --filter "FullyQualifiedName~@critical"
  
- name: Run full suite
  if: success()
  run: |
    dotnet test ./Tests.E2E/Tests.E2E.csproj

3. Retry Flaky Tests

- name: Run tests with retry
  run: |
    dotnet test ./Tests.E2E/Tests.E2E.csproj \
      -- NUnit.RetryFailedTests=2

4. Notify on Failure

- name: Notify on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    text: 'Tests failed!'
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Troubleshooting

Playwright Browsers Not Found

Ensure browsers are installed in the CI environment:

# Add to your pipeline dotnet build ./Tests.E2E/Tests.E2E.csproj bash ./Tests.E2E/bin/Debug/net9.0/playwright.sh install --with-deps chromium

Timeout Issues

Increase timeouts in CI:

env:
  PW_TIMEOUT_MS: 10000  # 10 seconds for CI

Memory Issues

Limit parallel workers:

dotnet test ./Tests.E2E/Tests.E2E.csproj -m:2 # Use 2 workers instead of 4