From 09581c356334756b4f6dad52e3549a2505f13680 Mon Sep 17 00:00:00 2001 From: chaxus Date: Tue, 3 Nov 2026 13:10:46 +0800 Subject: [PATCH] fix(ci): key the Playwright browser cache on the distro release ubuntu-latest moved to 26.04 and restored the WebKit build cached on 24.04, which cannot start there (libicudata.so.74 missing). Playwright ships one build per Ubuntu release, so the key now carries the distro and the runner arch. Co-Authored-By: Claude Opus 5.5 --- .github/actions/setup/action.yml | 10 +++-- CLAUDE.md | 2 +- .../2026-11-03-playwright-cache-distro.md | 42 +++++++++++++++++++ test/unit/workflow-contract.test.ts | 11 +++-- 4 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 docs/explorations/2026-11-03-playwright-cache-distro.md diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 5827afa2e..b49ad9856 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -35,17 +35,21 @@ runs: BROWSERS: ${{ inputs.browsers }} run: | echo "version=$(pnpm exec playwright --version | awk '{ print $NF }')" >>"$GITHUB_OUTPUT" + echo "distro=$(. /etc/os-release && echo "$ID$VERSION_ID")" >>"$GITHUB_OUTPUT" echo "slug=${BROWSERS// /-}" >>"$GITHUB_OUTPUT" - # The browser binaries are the slow half of the install and they only ever - # change with the Playwright version, so a hit leaves just the apt step. + # The browser binaries are the slow half of the install. Playwright ships a + # separate build per distro release (WebKit links against that release's + # ICU), so the key carries the distro too: when ubuntu-latest moved to + # 26.04 a key without it restored the 24.04 WebKit, which cannot start + # there (libicudata.so.74 missing). - name: Restore the Playwright browser cache if: inputs.browsers != '' id: browser-cache uses: actions/cache@v6 with: path: ~/.cache/ms-playwright - key: playwright-${{ runner.os }}-${{ steps.playwright.outputs.version }}-${{ steps.playwright.outputs.slug }} + key: playwright-${{ runner.os }}-${{ steps.playwright.outputs.distro }}-${{ runner.arch }}-${{ steps.playwright.outputs.version }}-${{ steps.playwright.outputs.slug }} - name: Install Playwright browsers if: inputs.browsers != '' diff --git a/CLAUDE.md b/CLAUDE.md index 707ed37cb..d20494b0c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -434,7 +434,7 @@ apt-get,而 hosted runner 上的 apt 有过**拉完 release 索引后彻底停 每次挂在不同的 job(三个 e2e job 跑的是同一步,谁中枪是随机的),每次都要人工 重跑。apt 自身没有总时长上限,所以 `.github/scripts/install-playwright.sh` 给 每次尝试套 `timeout` 并重试,重试前清掉被杀的 apt 留下的锁;浏览器二进制 -按 Playwright 版本号进 `actions/cache`,命中时只跑 `install-deps`。 +按"发行版 + 架构 + Playwright 版本号"进 `actions/cache`(Playwright 每个 Ubuntu 版本一套构建,2026-11-03 漏了发行版,26.04 的机器取回 24.04 的 WebKit 起不来),命中时只跑 `install-deps`。 **缓存命中时直接不跑 apt**(2026-08-19 起)。读健康 run 的日志才看清 `install-deps` 到底在干什么:Chromium 要的库(libnss3 / libgbm1 / libasound2t64 / libcairo2 …) diff --git a/docs/explorations/2026-11-03-playwright-cache-distro.md b/docs/explorations/2026-11-03-playwright-cache-distro.md new file mode 100644 index 000000000..d3aa6fc65 --- /dev/null +++ b/docs/explorations/2026-11-03-playwright-cache-distro.md @@ -0,0 +1,42 @@ +# 夜间跨浏览器全红:浏览器缓存没带发行版 + +2026-11-03 的 Nightly corpus(run 41561076181)cross-browser 红:WebKit 三个分片 + serial +全部 1ms 失败,Firefox 分片 2 有 4 条失败。 + +## 根因(WebKit) + +日志里每条 WebKit 用例都是同一句: + +``` +MiniBrowser: error while loading shared libraries: libicudata.so.74: cannot open shared object file +``` + +- `ubuntu-latest` 从这周起指向 **ubuntu-26.04**(10-30 那次跨浏览器还是 24.04,全绿; + 中间两晚 gate 判定没有新提交、跨浏览器没跑,所以这是 26.04 上第一次跑)。 +- Playwright 1.64 对每个 Ubuntu 版本发一套独立构建(`coreBundle.js` 里有 + `ubuntu24.04-x64` / `ubuntu26.04-x64` 两套下载项),WebKit 链接的是那个版本自己的 ICU。 +- `.github/actions/setup` 的缓存 key 是 `playwright-Linux-1.64.0-webkit`——没有发行版。 + 26.04 的机器命中了 24.04 时存进去的缓存,拿到的是 24.04 的 WebKit,而 26.04 上没有 ICU 74。 +- 命中缓存时安装脚本直接 `exit 0`(不跑 apt,见 CLAUDE.md CI 一节),所以也没有任何一步会 + 发现版本对不上。 + +## 改动 + +- 缓存 key 加上 `/etc/os-release` 的 `$ID$VERSION_ID` 与 `runner.arch`: + `playwright-Linux-ubuntu26.04-X64-1.64.0-webkit`。换镜像就是冷缓存,走完整安装 + (含 `install-deps`),之后再命中的才是同一发行版的构建。 +- `test/unit/workflow-contract.test.ts` 钉住 key 里的发行版段。反向验证:只撤 + action.yml 的改动,这条用例变红;恢复后 68/68 绿。 + +## Firefox 那 4 条 + +`agent-interface-affordances.spec.ts:65`:`Tab` 再 `Shift+Tab` 之后 +"Import structured result" 按钮没拿到焦点(`inactive`),4 个视口/主题组合全挂、重试也挂。 +Firefox 能启动,但跑的同样是 24.04 的构建,跑在 26.04 上。是不是同一个原因,本地(macOS) +复现不了;以修复后在分支上手动触发一次 nightly(`skip_corpus`)的结果为准,若仍红再单独查。 + +## 还没验证的一点 + +缓存命中时不跑 apt,前提是 runner 镜像本来就带齐浏览器要的库——这是 24.04 上读日志得出的 +结论,26.04 上没验证过。验证方法:在分支上手动跑两次 nightly(第一次冷缓存,第二次命中), +第二次 WebKit 也能起来才算闭环。 diff --git a/test/unit/workflow-contract.test.ts b/test/unit/workflow-contract.test.ts index e6bd59b52..aae205647 100644 --- a/test/unit/workflow-contract.test.ts +++ b/test/unit/workflow-contract.test.ts @@ -105,10 +105,15 @@ describe('the shared setup action', () => { expect(action).not.toMatch(/run: pnpm exec playwright install/); }); - it('caches the browsers against the Playwright version, not the lockfile', () => { + it('caches the browsers against the distro and Playwright version, not the lockfile', () => { // Keying on the lockfile would evict the cache on every dependency bump - // and re-download the browsers for no reason. - expect(action).toMatch(/key: playwright-\$\{\{ runner\.os \}\}-\$\{\{ steps\.playwright\.outputs\.version \}\}/); + // and re-download the browsers for no reason. The distro is part of the + // key because Playwright builds per release: without it the 24.04 WebKit + // was restored onto the 26.04 runner and could not start. + expect(action).toMatch(/distro=\$\(\. \/etc\/os-release && echo "\$ID\$VERSION_ID"\)/); + expect(action).toMatch( + /key: playwright-\$\{\{ runner\.os \}\}-\$\{\{ steps\.playwright\.outputs\.distro \}\}-\$\{\{ runner\.arch \}\}-\$\{\{ steps\.playwright\.outputs\.version \}\}/, + ); }); });