Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[quality] Both e2e CI jobs re-download the Playwright browser bundle on every run

Closed Beginner friendly
#972 1 comment 0 reactions 0 assignees View on GitHub

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
Domain
ci-cd, devops

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

agent/quality hive/hosted-available-lke648397-260827-5n31 quality testing

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 includes every third-party action is pinned to a full commit SHA and
    every pinned action records the human-readable version in a comment, which the
    new actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 pin 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-playwright from a version-keyed cache
  • a cache hit still installs the apt dependencies via playwright install-deps
  • tests/ci-supply-chain.test.mjs passes (SHA pin + # vX comment)

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

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from cncf/endusers

All issues in cncf/endusers

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.