mcpField
P
playwright-ci-caching

playwright-ci-caching

github.com/aaronontheweb云与 DevOps1.2k444 次安装今天更新
代码仓库

关于 playwright-ci-caching

这项技能介绍如何在 CI/CD 流水线中缓存 Playwright 浏览器,适用于维护端到端测试的开发者。内容涵盖基于版本的缓存键、GitHub Actions 和 Azure DevOps 配置,以及运行 Playwright CLI 的 PowerShell 脚本。

主要功能

  1. 01基于版本的浏览器缓存键
  2. 02按操作系统区分缓存路径
  3. 03缓存未命中时安装浏览器
  4. 04GitHub Actions 和 Azure DevOps 示例
  5. 05PowerShell Playwright CLI 辅助脚本

适用场景

  1. 01减少 CI 构建中的浏览器下载
  2. 02Playwright 升级后使缓存失效
  3. 03配置多操作系统 GitHub Actions 缓存

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/aaronontheweb/dotnet-skills --skill playwright-ci-caching

安装后在 Claude Code 中输入/playwright-ci-caching确认已加载。

详细介绍

在 CI/CD 中缓存 Playwright 浏览器

何时使用此技能

适用于以下情况:

  • 为包含 Playwright E2E 测试的项目设置 CI/CD
  • 浏览器下载(约 400MB,耗时 1–2 分钟)导致构建缓慢
  • 希望在 Playwright 版本变更时自动使缓存失效
  • 使用 GitHub Actions 或 Azure DevOps 管道

问题

默认情况下,每次运行 CI 都必须下载 Playwright 浏览器(约 400MB)。这会:

  • 为每次构建增加 1–2 分钟
  • 浪费带宽
  • 可能因临时网络问题而失败
  • 拖慢 PR 反馈循环

核心模式

  1. 提取 Playwright 版本:从 Directory.Packages.props(CPM)提取版本,用作缓存键
  2. 缓存浏览器二进制文件:使用适合相应平台的路径
  3. 按需安装:仅在缓存未命中时下载
  4. 自动使缓存失效:缓存键包含版本,因此升级软件包时缓存会失效

各操作系统的缓存路径

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

GitHub Actions

- name: Get Playwright Version
  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: Cache Playwright Browsers
  id: playwright-cache
  uses: actions/cache@v4
  with:
    path: ~/.cache/ms-playwright
    key: ${{ runner.os }}-playwright-${{ env.PlaywrightVersion }}

- name: Install Playwright Browsers
  if: steps.playwright-cache.outputs.cache-hit != 'true'
  shell: pwsh
  run: ./build/playwright.ps1 install --with-deps
多操作系统 GitHub Actions

适用于在多个操作系统上运行的工作流:

- name: Cache Playwright Browsers
  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: 'Get Playwright Version'
  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: 'Cache Playwright Browsers'
  inputs:
    key: 'playwright | "$(Agent.OS)" | $(PlaywrightVersion)'
    path: '$(HOME)/.cache/ms-playwright'
    cacheHitVar: 'PlaywrightCacheHit'

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

辅助脚本:playwright.ps1

创建 build/playwright.ps1 脚本,用于查找并运行 Playwright CLI。此脚本可屏蔽 Playwright CLI 的位置差异,该位置会因项目结构而异。

# build/playwright.ps1
# Discovers Microsoft.Playwright.dll and runs the bundled Playwright CLI

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

# Find the Playwright DLL (after 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 not found. Run 'dotnet build' first."
    exit 1
}

$playwrightDir = $playwrightDll.DirectoryName

# Find the playwright CLI (path varies by OS and node version)
$playwrightCmd = Get-ChildItem -Path "$playwrightDir/.playwright/node" -Recurse -Filter "playwright.cmd" -ErrorAction SilentlyContinue |
    Select-Object -First 1

if (-not $playwrightCmd) {
    # Try Unix executable
    $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 not found in $playwrightDir/.playwright/node"
    exit 1
}

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

用法:

# Install browsers
./build/playwright.ps1 install --with-deps

# Install specific browser
./build/playwright.ps1 install chromium

# Show installed browsers
./build/playwright.ps1 install --dry-run

先决条件

此模式假定:

  1. 使用 Directory.Packages.props 进行中央软件包管理(CPM):

    <Project>
      <ItemGroup>
        <PackageVersion Include="Microsoft.Playwright" Version="1.40.0" />
      </ItemGroup>
    </Project>
    
  2. 运行 playwright.ps1 前已构建项目(因此 DLL 已存在)

  3. CI Agent 上提供 PowerShell(GitHub Actions 和 Azure DevOps 已预装)

为什么基于版本的缓存键很重要

在缓存键中使用 Playwright 版本可确保:

  • 升级 Playwright 时自动使缓存失效
  • 不会使用与 SDK 版本不匹配的过期浏览器二进制文件
  • 版本升级后无需手动清除缓存

如果将缓存键写死(例如 playwright-browsers-v1),每次升级 Playwright 时都必须手动更新缓存键,否则就会遇到难以理解的版本不匹配错误。

故障排除

未使用缓存
  1. 确认版本提取步骤输出了正确的版本
  2. 检查缓存路径是否与操作系统匹配
  3. 确认 Directory.Packages.props 存在,且包含 Playwright 软件包
缓存命中后出现“找不到浏览器”

缓存的浏览器与 Playwright SDK 版本不匹配。出现这种情况的原因包括:

  • 缓存键未包含版本
  • 版本提取过程未报错但失败了

解决方法:确保缓存键中包含 Playwright 版本。

playwright.ps1 找不到 DLL

运行脚本前先执行 dotnet build 或 dotnet restore。Playwright DLL 仅在 NuGet 还原后才会存在。

参考资料

此模式已在生产项目中经过实战验证:

相关技能

  • dotnet-skills:playwright-blazor - 为 Blazor 应用编写 Playwright 测试
  • dotnet-skills:project-structure - 设置中央软件包管理

评论

支持 Markdown