From 0f91afa71bff50d6a1bd9fdb2f1f096fc3428e01 Mon Sep 17 00:00:00 2001 From: Charlie Croom Date: Tue, 15 Sep 2026 10:43:10 -0400 Subject: [PATCH] Key browser downloads by the installed Playwright version Co-authored-by: Amp Signed-off-by: Charlie Croom Amp-Thread-ID: https://ampcode.com/threads/T-01a0a149-b278-7550-acc4-356168b0c4b5 --- .github/actions/setup/action.yml | 7 ++- tests/integration/browser-ci.test.mjs | 69 ++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index dd671f3d..303a6062 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -28,12 +28,17 @@ runs: - name: Install locked dependencies shell: bash run: pnpm install --frozen-lockfile + - name: Resolve installed Playwright version + if: inputs.browsers == 'true' + id: playwright + shell: bash + run: node -p "'version=' + require('@playwright/test/package.json').version" >> "$GITHUB_OUTPUT" - name: Cache Playwright engines if: inputs.browsers == 'true' uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: ~/.cache/ms-playwright - key: playwright-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('pnpm-lock.yaml') }} + key: playwright-${{ runner.os }}-${{ runner.arch }}-${{ steps.playwright.outputs.version }}-chromium-webkit - name: Install pinned browser engines and libraries if: inputs.browsers == 'true' shell: bash diff --git a/tests/integration/browser-ci.test.mjs b/tests/integration/browser-ci.test.mjs index 7469116c..f6cb7cf8 100644 --- a/tests/integration/browser-ci.test.mjs +++ b/tests/integration/browser-ci.test.mjs @@ -1,7 +1,16 @@ import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; -import { readFileSync } from "node:fs"; +import { + mkdirSync, + mkdtempSync, + readFileSync, + rmSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join } from "node:path"; import test from "node:test"; +import { parse } from "yaml"; import config from "../browser/playwright.config.mjs"; import { run } from "../browser/run-command.mjs"; @@ -180,3 +189,61 @@ test("Hermit cache keys distinguish jobs that provision different tools", () => const setup = read(".github/actions/setup/action.yml"); assert.match(setup, /key: hermit-.*\$\{\{ github\.job \}\}/); }); + +test("browser cache follows the installed Playwright version, not unrelated dependency edits", (t) => { + const { steps } = parse(read(".github/actions/setup/action.yml")).runs; + const version = steps.find((step) => step.id === "playwright"); + const cache = steps.find((step) => step.name === "Cache Playwright engines"); + const install = steps.find( + (step) => step.name === "Install pinned browser engines and libraries", + ); + assert.ok(version, "resolve the installed version after the frozen install"); + assert.ok( + steps.findIndex((step) => step.run === "pnpm install --frozen-lockfile") < + steps.indexOf(version), + ); + assert.ok(steps.indexOf(version) < steps.indexOf(cache)); + assert.ok(steps.indexOf(cache) < steps.indexOf(install)); + for (const step of [version, cache, install]) + assert.equal(step.if, "inputs.browsers == 'true'"); + assert.equal( + install.run, + "pnpm exec playwright install --with-deps chromium webkit", + ); + assert.equal( + cache.with.key, + `playwright-\${{ runner.os }}-\${{ runner.arch }}-\${{ steps.playwright.outputs.version }}-chromium-webkit`, + ); + assert.equal(cache.with["restore-keys"], undefined); + + const cwd = mkdtempSync(join(tmpdir(), "buzz-playwright-version-")); + t.after(() => rmSync(cwd, { recursive: true, force: true })); + const manifest = join(cwd, "node_modules/@playwright/test/package.json"); + const output = join(cwd, "output"); + mkdirSync(dirname(manifest), { recursive: true }); + const resolve = () => { + writeFileSync(output, ""); + return spawnSync("bash", ["-e", "-c", version.run], { + cwd, + env: { ...process.env, GITHUB_OUTPUT: output }, + encoding: "utf8", + timeout: 5000, + }); + }; + for (const installed of ["1.60.0", "1.61.0"]) { + writeFileSync(manifest, JSON.stringify({ version: installed })); + for (const unrelated of ["before", "after"]) { + writeFileSync(join(cwd, "pnpm-lock.yaml"), unrelated); + const result = resolve(); + assert.equal(result.status, 0, result.stderr); + assert.equal(readFileSync(output, "utf8"), `version=${installed}\n`); + } + } + rmSync(manifest); + assert.notEqual( + resolve().status, + 0, + "missing installation must fail, not cache an empty version", + ); + assert.equal(readFileSync(output, "utf8"), ""); +});