Skip to content

CI: cache the system packages Playwright dowloads for WebKit - #80846

Merged
adimoldovan merged 8 commits into
trunkfrom
cache-playwright-binaries
Aug 3, 2026
Merged

CI: cache the system packages Playwright dowloads for WebKit#80846
adimoldovan merged 8 commits into
trunkfrom
cache-playwright-binaries

Conversation

@adimoldovan

@adimoldovan adimoldovan commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What?

Cache the Debian packages that npx playwright install --with-deps downloads. Install only Chromium in the two jobs that never launch another browser.

Why?

--with-deps fetches 114MB from azure.archive.ubuntu.com, and the mirror sometimes throttles it. Across the last six runs on trunk (54 jobs) the step took a median of 48 seconds, but three jobs took 917s, 987s and 1072s, and one took 56 minutes:

Fetched 114 MB in 56min 17s (33.8 kB/s)

This buys reliability, not speed. A healthy run fetches the same 114MB at 53.8 MB/s, in two seconds, so the cache saves almost nothing on a good day.

All 200 packages belong to WebKit.

Playwright advises against caching browser binaries, because restoring the cache costs about as much as the download, and because the system dependencies "are not cacheable". These measurements agree on the first point, so this caches the apt layer instead. It does not contradict the second: apt still installs the packages on every run, which takes about 11 seconds of dpkg work that no cache can remove. Only the download is cached.

How?

.github/setup-playwright copies the cached packages into /var/cache/apt/archives before installing, where apt finds them instead of downloading. The cache engages only when the browser list includes WebKit. Its key holds the runner OS and architecture, ImageOS, ImageVersion, the playwright-core version, the browser list, and a fingerprint of the packages themselves.

The action also gives the three workflows one place to install browsers, next to .github/setup-node. Each one used to carry its own copy of the command, and each browser list now states what that job actually launches.

The fingerprint keeps the cache fresh. A fixed key would go stale once a package is updated in apt. Instead, the save step runs only when the package set changed, writing a new entry and uploading nothing on an unchanged run.

install-deps still runs apt-get update, so 10.9MB of package lists still come from the mirror. This cuts the exposure roughly tenfold, not to zero.

Testing Instructions

  1. Confirm the end-to-end and Storybook workflows pass.
  2. Open a shard's "Install Playwright dependencies" step and find apt's Fetched 114 MB in ... line. This run seeds the cache.
  3. Re-run the workflow and read the same line. A working cache reports a far smaller figure.

Use of AI Tools

Opus 5: the CI log analysis, the composite action, the workflow changes, and adversarial review.
Sol-5.6: review.

`npx playwright install --with-deps` downloads 114MB of Debian packages
from the Ubuntu mirror. The mirror throttles that fetch often enough to
stall an end-to-end job: recent runs on trunk took 14, 15, 17 and 56
minutes on the step, against a median of 48 seconds.

Every one of those 200 packages belongs to WebKit. The runner image
already satisfies Chromium and Firefox, so those jobs download nothing.

Cache the packages through a composite action, and engage the cache only
when the browser list includes WebKit. Install Chromium alone in the two
jobs that never launch another browser: the RTC WebSocket suite matches
no spec tagged `@webkit` or `@firefox`, and the Storybook test runner
only launches Chromium.
@github-actions github-actions Bot added the First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository label Jul 29, 2026
@github-actions

Copy link
Copy Markdown

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @adimoldovan! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

Cache entries are immutable, so `actions/cache` does not save again on an
exact key hit. With a fixed key, any package that Ubuntu updates would be
re-downloaded on every run until the runner image rotated.

Put a fingerprint of the cached packages in the key and split the restore
and save steps. The save step runs only when the package set changed, so
an unchanged run uploads nothing and an updated one writes a new entry.
@adimoldovan adimoldovan changed the title CI: cache the system packages Playwright installs for WebKit [wip] CI: cache the system packages Playwright installs for WebKit Jul 29, 2026
@adimoldovan adimoldovan changed the title [wip] CI: cache the system packages Playwright installs for WebKit [wip] CI: cache the system packages Playwright dowloads for WebKit Jul 29, 2026
@adimoldovan adimoldovan self-assigned this Jul 29, 2026
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

Flaky tests detected in 389a30e.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/30643720620
📝 Reported issues:

@adimoldovan
adimoldovan marked this pull request as ready for review July 30, 2026 15:32
@adimoldovan
adimoldovan requested a review from desrosj as a code owner July 30, 2026 15:32
@adimoldovan adimoldovan changed the title [wip] CI: cache the system packages Playwright dowloads for WebKit CI: cache the system packages Playwright dowloads for WebKit Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: adimoldovan <adrianmoldovanwp@git.wordpress.org>
Co-authored-by: lancewillett <lancewillett@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@adimoldovan
adimoldovan requested a review from lancewillett July 30, 2026 15:32

@lancewillett lancewillett left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers.

  • Verified the composite action’s cache flow and workflow callers: a WebKit job restored the 109 MB package cache, while RTC and Storybook correctly skipped it for Chromium-only runs

AI use: gpt-5.6-sol

@Mamaduka

Copy link
Copy Markdown
Member

The Playwright documentation doesn't recommend caching browser binaries: https://playwright.dev/docs/ci#caching-browsers.

@adimoldovan

Copy link
Copy Markdown
Contributor Author

The Playwright documentation doesn't recommend caching browser binaries: playwright.dev/docs/ci#caching-browsers.

@Mamaduka and this PR doesn't do that, which is already mentioned in PR the description, along with the same link.
This is caching the system dependencies, the deb files apt downloads.

@Mamaduka Mamaduka added the [Type] Automated Testing Testing infrastructure changes impacting the execution of end-to-end (E2E) and/or unit tests. label Jul 30, 2026
@Mamaduka

Copy link
Copy Markdown
Member

Sorry, somehow I missed that 🙇

Resolve storybook-check.yml against #81017, which moved the smoke-test deps into the storybook workspace: keep that workspace refactor, and install browsers through .github/setup-playwright with chromium only.
Sort the fingerprint under LC_ALL=C so collation cannot perturb the hash, and install only Chromium in the Storybook workspace's setup script, matching what CI installs and what the test runner launches. Document why the exact cache key never matches, and what apt does and does not verify about a cached package.
@github-actions

Copy link
Copy Markdown

Size Change: 0 B

Total Size: 7.78 MB

compressed-size-action

@lancewillett
lancewillett self-requested a review July 31, 2026 18:37

@lancewillett lancewillett left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers found.

What I tested:

  • Reviewed the changes since the prior approval.
  • Confirmed Storybook and the composite action resolve Playwright 1.62.1.
  • Confirmed all Playwright shards, RTC, Storybook smoke, actionlint, and Zizmor passed.

Adversarial review · gpt-5.6-sol

@adimoldovan
adimoldovan merged commit 226fd44 into trunk Aug 3, 2026
48 checks passed
@adimoldovan
adimoldovan deleted the cache-playwright-binaries branch August 3, 2026 10:01
@github-actions github-actions Bot added this to the Gutenberg 23.8 milestone Aug 3, 2026
env:
BROWSERS: ${{ inputs.browsers }}
run: |
VERSION="$(node -p "require('playwright-core/package.json').version")"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will not work in isolated mode unless the dependency is explicitly declared.

See the failure on the PR where we are exploring the isolated dependencies.

A better solution is to delegate this to some workspace that has this as a dependency. Somewhat related changes were recetly made in #81017

sudo cp -r --update=none "$HOME/apt-cache/." /var/cache/apt/archives/

# shellcheck disable=SC2086 # The browser list is intentionally split into separate arguments.
npx playwright install $BROWSERS --with-deps

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the same reason as #81017, we don't want to use npx in CI workflows for security reasons.

BROWSERS_KEY="$(echo "${BROWSERS:-all}" | tr ' ' '-')"
# Packages cached under another runner image mostly miss.
IMAGE="${ImageOS:-unknown}-${ImageVersion:-unknown}"
echo "PREFIX=playwright-apt-${RUNNER_OS}-${RUNNER_ARCH}-${IMAGE}-${VERSION}-${BROWSERS_KEY}-" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it's better to add prefixes to the variables to make their end result readable in CI logs

For example, it currently outputs this

playwright-apt-Linux-X64-ubuntu24-20260720.247.2-1.62.1-chromium-firefox-webkit-afecb67c668a2145

From that string, it's difficult to understand what those numbers mean. I would expect it to be like this

"PREFIX=os-${RUNNER_OS}--arc-${RUNNER_ARCH}--img-${IMAGE}--playwright-${VERSION}--browsers-${BROWSERS_KEY}-" 

which would result in

os-Linux-X64--arc-ubuntu24-20260720.247.2--playwright-1.62.1--browsers-chromium-firefox-webkit-afecb67c668a2145

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository [Type] Automated Testing Testing infrastructure changes impacting the execution of end-to-end (E2E) and/or unit tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants