关于 playwright-ci-caching
这项技能介绍如何在 CI/CD 流水线中缓存 Playwright 浏览器,适用于维护端到端测试的开发者。内容涵盖基于版本的缓存键、GitHub Actions 和 Azure DevOps 配置,以及运行 Playwright CLI 的 PowerShell 脚本。
主要功能
- 01基于版本的浏览器缓存键
- 02按操作系统区分缓存路径
- 03缓存未命中时安装浏览器
- 04GitHub Actions 和 Azure DevOps 示例
- 05PowerShell Playwright CLI 辅助脚本
适用场景
- 01减少 CI 构建中的浏览器下载
- 02Playwright 升级后使缓存失效
- 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 反馈循环
核心模式
- 提取 Playwright 版本:从
Directory.Packages.props(CPM)提取版本,用作缓存键 - 缓存浏览器二进制文件:使用适合相应平台的路径
- 按需安装:仅在缓存未命中时下载
- 自动使缓存失效:缓存键包含版本,因此升级软件包时缓存会失效
各操作系统的缓存路径
| 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
先决条件
此模式假定:
-
使用
Directory.Packages.props进行中央软件包管理(CPM):<Project> <ItemGroup> <PackageVersion Include="Microsoft.Playwright" Version="1.40.0" /> </ItemGroup> </Project> -
运行
playwright.ps1前已构建项目(因此 DLL 已存在) -
CI Agent 上提供 PowerShell(GitHub Actions 和 Azure DevOps 已预装)
为什么基于版本的缓存键很重要
在缓存键中使用 Playwright 版本可确保:
- 升级 Playwright 时自动使缓存失效
- 不会使用与 SDK 版本不匹配的过期浏览器二进制文件
- 版本升级后无需手动清除缓存
如果将缓存键写死(例如 playwright-browsers-v1),每次升级 Playwright 时都必须手动更新缓存键,否则就会遇到难以理解的版本不匹配错误。
故障排除
未使用缓存
- 确认版本提取步骤输出了正确的版本
- 检查缓存路径是否与操作系统匹配
- 确认
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- 设置中央软件包管理