CommunityCodierung & Entwicklunggithub.com

Playwright-CI-Caching

Cachet Playwright-Browser-Binärdateien in CI/CD-Pipelines (GitHub Actions, Azure DevOps), um den 1-2-minütigen Download-Overhead bei jedem Build zu vermeiden.

Was ist Playwright-CI-Caching?

Dieser Skill beschreibt, wie Playwright-Browser-Binärdateien in CI/CD-Pipelines (GitHub Actions und Azure DevOps) effizient gecached werden, um Buildzeiten zu verkürzen. Standardmäßig müssen die ~400 MB großen Browser-Binärdateien bei jedem CI-Durchlauf heruntergeladen werden, was 1-2 Minuten zusätzlicher Zeit, Bandbreitenverschwendung und potenzielle Netzwerkfehler verursacht. Die Kernlösung extrahiert die Playwright-Version aus einer `Directory.Packages.props`-Datei (Central Package Management) und verwendet sie als Cache-Schlüssel. Bei einem Cache-Treffer werden die Browser aus dem Cache geladen; bei einem Fehlschlag werden sie nur dann installiert. Der Versions-basierte Cache-Schlüssel sorgt für automatische Invalidierung, wenn die Playwright-Version aktualisiert wird. Das Repository enthält außerdem ein PowerShell-Hilfsskript (`playwright.ps1`), das die Playwright-CLI automatisch erkennt und ausführt. Der Skill behandelt plattformspezifische Cache-Pfade (Linux, macOS, Windows) und bietet vollständige YAML-Konfigurationen für beide CI-Plattformen sowie Fehlerbehebungshinweise.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Aaronontheweb/dotnet-skills/tree/main/skills/playwright-ci-caching

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Caching von Playwright-Browsern in CI/CD

Wann dieser Skill verwendet werden sollte

Verwenden Sie diesen Skill, wenn:

  • Sie CI/CD für ein Projekt mit Playwright-E2E-Tests einrichten
  • Build-Zeiten aufgrund von Browser-Downloads (~400 MB, 1-2 Minuten) langsam sind
  • Sie eine automatische Cache-Invalidierung wünschen, wenn sich die Playwright-Version ändert
  • Sie GitHub Actions oder Azure DevOps-Pipelines verwenden

Das Problem

Playwright-Browser (~400 MB) müssen bei jedem CI-Durchlauf standardmäßig heruntergeladen werden. Dies:

  • Fügt jedem Build 1-2 Minuten hinzu
  • Verschwendet Bandbreite
  • Kann bei vorübergehenden Netzwerkproblemen fehlschlagen
  • Verlangsamt PR-Feedbackschleifen

Kernmuster

  1. Playwright-Version extrahieren aus Directory.Packages.props (CPM) zur Verwendung als Cache-Schlüssel
  2. Browser-Binärdateien cachen mittels plattformgerechter Pfade
  3. Bedingte Installation – nur bei Cache-Fehlschlag herunterladen
  4. Automatischer Cache-Bust – Schlüssel enthält Version, sodass Paketupgrades den Cache invalidieren

Cache-Pfade nach Betriebssystem

BetriebssystemPfad
Linux~/.cache/ms-playwright
macOS~/Library/Caches/ms-playwright
Windows%USERPROFILE%\AppData\Local\ms-playwright

GitHub Actions

- name: Playwright-Version abrufen
  shell: pwsh
  run: |
    $propsPath = "Directory.Packages.props"
    [xml]$props = Get-Content $propsPath
    $version = $props.Project.ItemGroup.PackageVersion |
      Where-Object { $_.Include -eq "Microsoft.Playwright" } |
      Select-Object -ExpandProperty Version
    echo "PlaywrightVersion=$version" >> $env:GITHUB_ENV

- name: Playwright-Browser cachen
  id: playwright-cache
  uses: actions/cache@v4
  with:
    path: ~/.cache/ms-playwright
    key: ${{ runner.os }}-playwright-${{ env.PlaywrightVersion }}

- name: Playwright-Browser installieren
  if: steps.playwright-cache.outputs.cache-hit != 'true'
  shell: pwsh
  run: ./build/playwright.ps1 install --with-deps

Multi-OS GitHub Actions

Für Workflows, die auf mehreren Betriebssystemen ausgeführt werden:

- name: Playwright-Browser cachen
  id: playwright-cache
  uses: actions/cache@v4
  with:
    path: |
      ~/.cache/ms-playwright
      ~/Library/Caches/ms-playwright
      ~/AppData/Local/ms-playwright
    key: ${{ runner.os }}-playwright-${{ env.PlaywrightVersion }}

Azure DevOps

- task: PowerShell@2
  displayName: 'Playwright-Version abrufen'
  inputs:
    targetType: 'inline'
    script: |
      [xml]$props = Get-Content "Directory.Packages.props"
      $version = $props.Project.ItemGroup.PackageVersion |
        Where-Object { $_.Include -eq "Microsoft.Playwright" } |
        Select-Object -ExpandProperty Version
      Write-Host "##vso[task.setvariable variable=PlaywrightVersion]$version"

- task: Cache@2
  displayName: 'Playwright-Browser cachen'
  inputs:
    key: 'playwright | "$(Agent.OS)" | $(PlaywrightVersion)'
    path: '$(HOME)/.cache/ms-playwright'
    cacheHitVar: 'PlaywrightCacheHit'

- task: PowerShell@2
  displayName: 'Playwright-Browser installieren'
  condition: ne(variables['PlaywrightCacheHit'], 'true')
  inputs:
    filePath: 'build/playwright.ps1'
    arguments: 'install --with-deps'

Hilfsskript: playwright.ps1

Erstellen Sie ein build/playwright.ps1-Skript, das die Playwright-CLI erkennt und ausführt. Dies abstrahiert den Speicherort der Playwright-CLI, der je nach Projektstruktur variiert.

# build/playwright.ps1
# Erkennt Microsoft.Playwright.dll und führt die gebündelte Playwright-CLI aus

param(
    [Parameter(ValueFromRemainingArguments = $true)]
    [string[]]$Arguments
)

# Finden der Playwright-DLL (nach dotnet build/restore)
$playwrightDll = Get-ChildItem -Path . -Recurse -Filter "Microsoft.Playwright.dll" -ErrorAction SilentlyContinue |
    Select-Object -First 1

if (-not $playwrightDll) {
    Write-Error "Microsoft.Playwright.dll nicht gefunden. Führen Sie zuerst 'dotnet build' aus."
    exit 1
}

$playwrightDir = $playwrightDll.DirectoryName

# Finden der Playwright-CLI (Pfad variiert je nach Betriebssystem und Node-Version)
$playwrightCmd = Get-ChildItem -Path "$playwrightDir/.playwright/node" -Recurse -Filter "playwright.cmd" -ErrorAction SilentlyContinue |
    Select-Object -First 1

if (-not $playwrightCmd) {
    # Unix-ausführbare Datei versuchen
    $playwrightCmd = Get-ChildItem -Path "$playwrightDir/.playwright/node" -Recurse -Filter "playwright" -ErrorAction SilentlyContinue |
        Where-Object { $_.Name -eq "playwright" } |
        Select-Object -First 1
}

if (-not $playwrightCmd) {
    Write-Error "Playwright-CLI nicht gefunden in $playwrightDir/.playwright/node"
    exit 1
}

Write-Host "Verwende Playwright-CLI: $($playwrightCmd.FullName)"
& $playwrightCmd.FullName @Arguments

Verwendung:

# Browser installieren
./build/playwright.ps1 install --with-deps

# Bestimmten Browser installieren
./build/playwright.ps1 install chromium

# Installierte Browser anzeigen
./build/playwright.ps1 install --dry-run

Voraussetzungen

Dieses Muster setzt voraus:

  1. Central Package Management (CPM) mit Directory.Packages.props:

    <Project>
      <ItemGroup>
        <PackageVersion Include="Microsoft.Playwright" Version="1.40.0" />
      </ItemGroup>
    </Project>
    
  2. Das Projekt wurde erstellt bevor playwright.ps1 ausgeführt wird (damit DLLs existieren)

  3. PowerShell verfügbar auf CI-Agenten (vorinstalliert auf GitHub Actions und Azure DevOps)

Warum Versionsbasierte Cache-Schlüssel wichtig sind

Die Verwendung der Playwright-Version im Cache-Schlüssel stellt sicher:

  • Automatische Invalidierung bei einem Upgrade von Playwright
  • Keine veralteten Browser-Binärdateien, die nicht zur SDK-Version passen
  • Kein manuelles Leeren des Caches nach Versionssprüngen erforderlich

Wenn Sie den Cache-Schlüssel fest codieren (z. B. playwright-browsers-v1), müssen Sie ihn bei jedem Upgrade von Playwright manuell erhöhen, oder Sie erhalten kryptische Versionskonfliktfehler.

Fehlerbehebung

Cache wird nicht verwendet

  1. Überprüfen Sie, ob der Schritt zur Versionsextraktion die korrekte Version ausgibt
  2. Prüfen Sie, ob der Cache-Pfad Ihrem Betriebssystem entspricht
  3. Stellen Sie sicher, dass Directory.Packages.props existiert und das Playwright-Paket enthält

"Browser nicht gefunden" nach Cache-Treffer

Die gecachten Browser entsprechen nicht der Playwright-SDK-Version. Dies passiert, wenn:

  • Der Cache-Schlüssel die Version nicht enthält
  • Die Versionsextraktion stillschweigend fehlgeschlagen ist

Lösung: Stellen Sie sicher, dass die Playwright-Version im Cache-Schlüssel enthalten ist.

playwright.ps1 kann die DLL nicht finden

Führen Sie dotnet build oder dotnet restore vor dem Skript aus. Die Playwright-DLL existiert erst nach der NuGet-Wiederherstellung.

Referenzen

Dieses Muster ist in Produktionsprojekten erprobt:

Verwandte Skills

  • dotnet-skills:playwright-blazor – Schreiben von Playwright-Tests für Blazor-Anwendungen
  • dotnet-skills:project-structure – Einrichtung des Central Package Management

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

akka-hosting-actor-patterns

Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.

akka-net-aspire-configuration

Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering, persistence, Akka.Management integration, and Aspire orchestration patterns.

akka-net-best-practices

Critical Akka.NET best practices including EventStream vs DistributedPubSub, supervision strategies, error handling, Props vs DependencyResolver, work distribution patterns, and cluster/local mode abstractions for testability.

akka-net-management

Akka.Management for cluster bootstrapping, service discovery (Kubernetes, Azure, Config), health checks, and dynamic cluster formation without static seed nodes.

akka-net-testing-patterns

Write unit and integration tests for Akka.NET actors using modern Akka.Hosting.TestKit patterns. Covers dependency injection, TestProbes, persistence testing, and actor interaction verification. Includes guidance on when to use traditional TestKit.

api-design

Design stable, compatible public APIs using extend-only design principles. Manage API compatibility, wire compatibility, and versioning for NuGet packages and distributed systems.

aspire-configuration

Configure Aspire AppHost to emit explicit app config via environment variables; keep app code free of Aspire clients and service discovery.

aspire-integration-testing

Write integration tests using .NET Aspire

aspire-service-defaults

Create a shared ServiceDefaults project for Aspire applications. Centralizes OpenTelemetry, health checks, resilience, and service discovery configuration across all services.

crap-analysis

Analyze code coverage and CRAP (Change Risk Anti-Patterns) scores to identify high-risk code. Use OpenCover format with ReportGenerator for Risk Hotspots showing cyclomatic complexity and untested code paths.

csharp-concurrency-patterns

Choosing the right concurrency abstraction in .NET - from async/await for I/O to Channels for producer/consumer to Akka.NET for stateful entity management. Avoid locks and manual synchronization unless absolutely necessary.

database-performance

Database access patterns for performance. Separate read/write models, avoid N+1 queries, use AsNoTracking, apply row limits, and never do application-side joins. Works with EF Core and Dapper.

dependency-injection-patterns

Organize DI registrations using IServiceCollection extension methods. Group related services into composable Add* methods for clean Program.cs and reusable configuration in tests.

dotnet-devcert-trust

Diagnose and fix .NET HTTPS dev certificate trust issues on Linux. Covers the full certificate lifecycle from generation to system CA bundle inclusion, with distro-specific guidance for Ubuntu, Fedora, Arch, and WSL2.

dotnet-local-tools

Managing local .NET tools with dotnet-tools.json for consistent tooling across development environments and CI/CD pipelines.

dotnet-project-structure

Modern .NET project structure including .slnx solution format, Directory.Build.props, central package management, SourceLink, version management with RELEASE_NOTES.md, and SDK pinning with global.json.

dotnet-slopwatch

Use Slopwatch to detect LLM reward hacking in .NET code changes. Run after every code modification to catch disabled tests, suppressed warnings, empty catch blocks, and other shortcuts that mask real problems.

efcore-patterns

Entity Framework Core best practices including NoTracking by default, query splitting for navigation collections, migration management, dedicated migration services, and common pitfalls to avoid.

ilspy-decompile

Understand implementation details of .NET code by decompiling assemblies. Use when you want to see how a .NET API works internally, inspect NuGet package source, view framework implementation, or understand compiled .NET binaries.

mailpit-integration

Test email sending locally using Mailpit with .NET Aspire. Captures all outgoing emails without sending them. View rendered HTML, inspect headers, and verify delivery in integration tests.

Verwandte Skills