Skip to content
85 changes: 85 additions & 0 deletions .github/setup-playwright/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: 'Install Playwright browsers'
description: 'Install Playwright browsers and their system dependencies, caching the Debian packages that WebKit needs.'

inputs:
browsers:
description: 'Optional. Space separated list of browsers to install. When not specified, all browsers are installed.'
required: false

runs:
using: 'composite'
steps:
# Only WebKit pulls system dependencies on the runner images, and the
# Ubuntu mirror throttles them often enough to stall a job for tens of
# minutes.
- name: Prepare the package cache
id: prepare
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

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


if [ -z "$BROWSERS" ] || [ "${BROWSERS#*webkit}" != "$BROWSERS" ]; then
echo "CACHE_DEPS=true" >> "$GITHUB_OUTPUT"
else
echo "CACHE_DEPS=false" >> "$GITHUB_OUTPUT"
fi

echo 'APT::Keep-Downloaded-Packages "true";' | sudo tee /etc/apt/apt.conf.d/99keep-downloaded-packages > /dev/null
mkdir -p "$HOME/apt-cache"
shell: bash

# The key carries a fingerprint of the packages, so a cache entry is
# never stale: when apt fetches a newer package the fingerprint changes
# and the save step writes a new entry. Cache entries are immutable, so
# refreshing one is not an option. `key` therefore never matches on its
# own; the prefix search restores the newest entry.
- name: Restore the cached packages
if: ${{ steps.prepare.outputs.CACHE_DEPS == 'true' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/apt-cache
key: ${{ steps.prepare.outputs.PREFIX }}
restore-keys: ${{ steps.prepare.outputs.PREFIX }}

- name: Install Playwright browsers and system dependencies
id: install
env:
BROWSERS: ${{ inputs.browsers }}
run: |
fingerprint() {
find "$HOME/apt-cache" -maxdepth 1 -name '*.deb' -printf '%f\n' | LC_ALL=C sort | sha256sum | cut -c1-16
}
BEFORE="$(fingerprint)"

# apt looks packages up by name, version and arch, re-downloading
# any whose size does not match its own index, so a stale package
# here is never used. It does not re-checksum what it finds cached.
# `--update=none` needs coreutils 9.3+, so ubuntu-24.04 or newer.
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.


sudo find /var/cache/apt/archives -maxdepth 1 -name '*.deb' -exec cp --update=none -t "$HOME/apt-cache" {} +
sudo chown -R "$(id -u):$(id -g)" "$HOME/apt-cache"

AFTER="$(fingerprint)"
echo "FINGERPRINT=$AFTER" >> "$GITHUB_OUTPUT"
if [ "$BEFORE" != "$AFTER" ]; then
echo "CHANGED=true" >> "$GITHUB_OUTPUT"
else
echo "CHANGED=false" >> "$GITHUB_OUTPUT"
fi
shell: bash

- name: Save the packages
if: ${{ steps.prepare.outputs.CACHE_DEPS == 'true' && steps.install.outputs.CHANGED == 'true' }}
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/apt-cache
key: ${{ steps.prepare.outputs.PREFIX }}${{ steps.install.outputs.FINGERPRINT }}
11 changes: 7 additions & 4 deletions .github/workflows/end2end-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ jobs:
run: npm run build -- --skip-types

- name: Install Playwright dependencies
run: |
npx playwright install chromium firefox webkit --with-deps
uses: ./.github/setup-playwright
with:
browsers: chromium firefox webkit

- name: Install WordPress and start the server
run: |
Expand Down Expand Up @@ -95,9 +96,11 @@ jobs:
- name: Npm build
run: npm run build -- --skip-types

# No collaboration spec is tagged `@webkit` or `@firefox`.
- name: Install Playwright dependencies
run: |
npx playwright install chromium firefox webkit --with-deps
uses: ./.github/setup-playwright
with:
browsers: chromium

- name: Install WordPress and start the server
run: |
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/storybook-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ jobs:
NODE_ENV: test
run: npm run storybook:e2e:build

# The Storybook test runner only launches Chromium.
- name: Install Playwright browsers
run: npm run --workspace @wordpress/storybook test:smoke:setup
uses: ./.github/setup-playwright
with:
browsers: chromium

- name: Serve Storybook and run tests
run: npm run --workspace @wordpress/storybook test:smoke
4 changes: 2 additions & 2 deletions .github/workflows/workflow-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ on:
paths:
# Only run when changes are made to workflow files.
- '.github/workflows/**'
- '.github/setup-node/action.yml'
- '.github/*/action.yml'
- 'packages/**/action.yml'
pull_request:
branches:
- trunk
paths:
# Only run when changes are made to workflow files.
- '.github/workflows/**'
- '.github/setup-node/action.yml'
- '.github/*/action.yml'
- 'packages/**/action.yml'
workflow_dispatch:

Expand Down
2 changes: 1 addition & 1 deletion storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,6 @@
"storybook:build": "NODE_OPTIONS=--max-old-space-size=8192 storybook build -c . -o ./build && node ./scripts/inject-legacy-docgen.mjs ./build/manifests/components.json",
"storybook:dev": "storybook dev -c . -p 50240",
"test:smoke": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"http-server ./build --port 50240 --silent\" \"wait-on tcp:127.0.0.1:50240 && test-storybook --url http://localhost:50240 --config-dir .\"",
"test:smoke:setup": "playwright install --with-deps"
"test:smoke:setup": "playwright install chromium --with-deps"
}
}
Loading