[quality] Both e2e CI jobs re-download the Playwright browser bundle on every run
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 68/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- github-actions, javascript, playwright
Research direction
Read .github/workflows/ci.yml around the e2e and e2e-coverage jobs, where Playwright browsers are installed. Follow the version-keyed cache approach described in the issue, ensuring cache hits still install system dependencies. Run node --test tests/ci-supply-chain.test.mjs tests/automation-workflow-ordering.test.mjs tests/workflow-scripts.test.mjs and npx prettier --check .github/workflows/ci.yml; done when both jobs restore the browser cache and the completion criteria pass.
Written by the indexing model from the issue text.
Description
Finding
Every pull request runs the Playwright browser suite twice, and both runs
re-download the Chromium bundle from scratch because nothing caches
~/.cache/ms-playwright.
.github/workflows/ci.yml has two jobs that each run
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
at :122 (e2e) and :163 (e2e-coverage). No workflow in the repository uses
actions/cache for the browser bundle — grep -n 'actions/cache' .github/workflows/*.yml
returns nothing. actions/setup-node is configured with cache: npm in all five jobs
that need it, so the npm half is already cached; only the browser half is not.
Evidence
Step and job durations for the last six Validate repository runs
(gh api repos/cncf/endusers/actions/runs/<id>/jobs, collected 2026-10-02):
| run | job | Install Playwright browsers |
test step | whole job |
|---|---|---|---|---|
| 36972418667 | e2e |
24s | 144s | 191s |
| 36972418667 | e2e-coverage |
22s | 175s | 262s |
| 36964738152 | e2e |
21s | 153s | 200s |
| 36964738152 | e2e-coverage |
22s | 168s | 253s |
| 36955631483 | e2e |
26s | 154s | 210s |
| 36955631483 | e2e-coverage |
24s | 173s | 266s |
| 36952783798 | e2e |
22s | 150s | 196s |
| 36952783798 | e2e-coverage |
22s | 171s | 257s |
| 36942712509 | e2e |
21s | 150s | 201s |
| 36942712509 | e2e-coverage |
20s | 162s | 244s |
| 36942086938 | e2e |
161s | 153s | 339s |
| 36942086938 | e2e-coverage |
21s | 158s | 238s |
Median install is 22s per job, so ~44s of every PR is spent re-fetching a bundle that
only changes when @playwright/test is bumped (currently ^1.63.0, resolving to
1.63.0). Run 36942086938 shows the tail this exposes: one cold fetch took 161s and
pushed that job from ~200s to 339s.
Recommendation
Cache the browser bundle, keyed on the resolved Playwright version. The apt packages
behind --with-deps are not cacheable, so a cache hit still has to run
playwright install-deps; the patch below keeps that correct rather than skipping the
install step outright.
Verified patch (applies to 0c87310):
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0bf3ef2..b594d2c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -118,8 +118,26 @@ jobs:
cache: npm
- name: Install dependencies
run: npm ci
+ - name: Resolve Playwright version
+ id: playwright
+ run: |
+ version="$(node -p "require('@playwright/test/package.json').version")"
+ echo "version=$version" >> "$GITHUB_OUTPUT"
+ - name: Restore Playwright browsers
+ id: playwright-cache
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
+ with:
+ path: ~/.cache/ms-playwright
+ key:
+ ${{ runner.os }}-playwright-${{ steps.playwright.outputs.version }}
+ # The browser download is cacheable; the apt packages behind
+ # --with-deps are not, so a cache hit still has to install those.
- name: Install Playwright browsers
+ if: steps.playwright-cache.outputs.cache-hit != 'true'
run: npx playwright install --with-deps chromium
+ - name: Install Playwright system dependencies
+ if: steps.playwright-cache.outputs.cache-hit == 'true'
+ run: npx playwright install-deps chromium
- name: Build production site
# Deliberately built without SITE_URL/BASE_URL: the suite navigates
# with paths relative to the site root (playwright.config.js sets
@@ -159,8 +177,26 @@ jobs:
cache: npm
- name: Install dependencies
run: npm ci
+ - name: Resolve Playwright version
+ id: playwright
+ run: |
+ version="$(node -p "require('@playwright/test/package.json').version")"
+ echo "version=$version" >> "$GITHUB_OUTPUT"
+ - name: Restore Playwright browsers
+ id: playwright-cache
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
+ with:
+ path: ~/.cache/ms-playwright
+ key:
+ ${{ runner.os }}-playwright-${{ steps.playwright.outputs.version }}
+ # The browser download is cacheable; the apt packages behind
+ # --with-deps are not, so a cache hit still has to install those.
- name: Install Playwright browsers
+ if: steps.playwright-cache.outputs.cache-hit != 'true'
run: npx playwright install --with-deps chromium
+ - name: Install Playwright system dependencies
+ if: steps.playwright-cache.outputs.cache-hit == 'true'
+ run: npx playwright install-deps chromium
- name: Initialize coverage run
run: >-
node tests/tools/e2e-coverage-run.mjs init --dir "$RUN_DIR" --run-id
Verification already performed
With the patch above applied locally at 0c87310:
node --test tests/ci-supply-chain.test.mjs tests/automation-workflow-ordering.test.mjs tests/workflow-scripts.test.mjs— 43 passed, 0 failed
(this includesevery third-party action is pinned to a full commit SHAand
every pinned action records the human-readable version in a comment, which the
newactions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0pin satisfies)npx prettier --check .github/workflows/ci.yml— clean
The pin resolves actions/cache tag v6.1.0
(gh api repos/actions/cache/git/ref/tags/v6.1.0 -> 55cc8345863c7cc4c66a329aec7e433d2d1c52a9,
object type commit), matching the repository's existing SHA-pin-plus-# vX-comment
convention.
A second, larger cost this measurement exposed — maintainer decision, not included above
e2e-coverage is continue-on-error: true and re-runs the entire Playwright suite
(158-175s) that the gating e2e job has already run (144-154s). That is ~5 minutes of
duplicated browser work per PR for a signal that, by design, never blocks a merge.
I am deliberately not proposing a patch for this. The two jobs build differently --
e2e uses npm run build:production and e2e-coverage uses npm run build:e2e:coverage
(E2E_COVERAGE=1, source-mapped) -- so collapsing them would change what the required
check actually gates, and restricting e2e-coverage to merge_group/main would drop
per-PR coverage feedback. Both are judgement calls for a maintainer, and either would be
a weakening of the current contract if done unilaterally. Recording it here so the cost
is visible alongside the measurement that found it.
Why this needs a human (no PR from this lane)
The change lives entirely in .github/workflows/ci.yml. A push touching
.github/workflows/** is rejected server-side at this agent's token tier regardless of
what the App installation grants, so no PR from this lane can ever contain it. The patch
above is exact and verified locally, so applying it is mechanical. It needs a human or an
ISSUES_PRS_MERGE agent to land.
Completion criteria
- both e2e jobs restore
~/.cache/ms-playwrightfrom a version-keyed cache - a cache hit still installs the apt dependencies via
playwright install-deps -
tests/ci-supply-chain.test.mjspasses (SHA pin +# vXcomment)
Priority
- Impact: medium
- Effort: low
Filed by quality agent (hold-gated mode)
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 0c87310
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
- Dominant language
- JavaScript
- Stars
- 0
- Forks
- 2
- Avg merge
- 13h 43m
- Merged PRs (30d)
- 600
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cncf/endusers
-
[guide] Three docs still cite the /awards route removed by #1552Possibly taken @hivecommons-hive claimed this today. Open🐝 covered by PR documentation hive/claimed-by-guide
Difficulty 1/5 1-3 hours Newbie friendliness 20/100
cncf/endusers#1568 · 1 comment ·
Maintainers usually reply within 1 day
-
[quality] Node-major parity chain in tests/dev-environment.test.mjs is blind to composite actions under .github/actions/**Possibly taken @hivecommons-hive claimed this 1 day ago. Open🐝 covered by PR agent/quality hive/claimed-by-quality hive/hosted-available-lke648397-260827-5n31 quality testing
Difficulty 3/5 1-2 days Newbie friendliness 20/100
cncf/endusers#1566 · 1 comment ·
Maintainers usually reply within 1 day
-
[quality] CI supply-chain and npm-script guards never scan .github/actions/** composite actionsPossibly taken @hivecommons-hive claimed this 1 day ago. Open🐝 covered by PR agent/quality hive/claimed-by-quality hive/hosted-available-lke648397-260827-5n31 quality testing
Difficulty 4/5 3-5 days Newbie friendliness 25/100
cncf/endusers#1564 · 1 comment ·
Maintainers usually reply within 1 day
-
🐝 covered by PR agent/architect architecture hive/hosted-available-lke648397-260827-5n31 tech-debt
Difficulty 4/5 3-5 days Newbie friendliness 35/100
cncf/endusers#1558 · 3 comments ·
Maintainers usually reply within 1 day
-
agent/quality hive/hosted-available-lke648397-260827-5n31 needs-decision quality testing
Difficulty 4/5 1-2 days Newbie friendliness 42/100
cncf/endusers#1556 · 7 comments ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
keyxmakerx/Chronicle#1532 ·
Maintainers usually reply within 1 day
-
enhancement feature good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
bug lsp sev-3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
Miaotofu01/Study-Mate#206 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 95/100
Uuriko/project-room#3998 ·
Maintainers usually reply within 1 day