From d5d235e32a544b74da50b8ff4bc0eb6b4ee9a446 Mon Sep 17 00:00:00 2001 From: Joe Fusco Date: Wed, 19 Aug 2026 15:38:34 -0700 Subject: [PATCH] fix: bound Playwright browser install with a timeout and retry A hung archive.ubuntu.com mirror let `playwright install --with-deps` sit silently for 27+ minutes, burning the job's full 30-minute timeout-minutes budget on a single stalled apt-get fetch instead of failing fast. Wrap each install attempt in `timeout 5m` and retry once, so a stalled mirror fails or recovers within ~10 minutes instead of consuming the whole job. Also restores the Playwright browser cache key fix (key on the resolved Playwright version, not the full lockfile hash) that was written but never actually merged to main -- it only existed on the stale fix/revert-hanging-globalsetup-warmup branch, which got squash-merged before that particular commit was cherry-picked over. --- .github/workflows/playwright.yml | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 73f37b4..c310a61 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -44,14 +44,20 @@ jobs: - name: Install Composer dependencies run: composer install --no-interaction + # Keyed on the resolved Playwright version rather than the whole + # lockfile hash, so unrelated dependency bumps don't invalidate a + # perfectly good browser cache -- only an actual Playwright version + # change should force a re-download. + - name: Get installed Playwright version + id: playwright-version + run: echo "version=$(npx playwright --version | awk '{print $2}')" >> "$GITHUB_OUTPUT" + - name: Cache Playwright browsers id: cache-playwright uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 with: path: ~/.cache/ms-playwright - key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }} - restore-keys: | - playwright-${{ runner.os }}- + key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }} # --with-deps runs apt-get to install OS-level libraries every time, # even when the browser binary itself is already cached. Those @@ -59,8 +65,20 @@ jobs: # they don't need reinstalling on a cache hit -- skipping apt-get here # avoids depending on the package mirror being fast (or up) on every # single run. + # + # apt-get has no default timeout, so a stalled mirror hangs silently + # until the job's own timeout-minutes kills the whole run (seen live: + # a dead archive.ubuntu.com mirror ate a full 30 minutes). Wrapping in + # `timeout` bounds each attempt, and retrying once covers a mirror + # that's back after a minute rather than failing the run outright. - name: Install Playwright browsers - run: npx playwright install ${{ steps.cache-playwright.outputs.cache-hit == 'true' && '' || '--with-deps' }} chromium + env: + CACHE_HIT: ${{ steps.cache-playwright.outputs.cache-hit }} + run: | + args=() + [ "$CACHE_HIT" = "true" ] || args+=(--with-deps) + timeout 5m npx playwright install "${args[@]}" chromium || \ + timeout 5m npx playwright install "${args[@]}" chromium # Restores the most recent cached checkout as a starting point, then # build-gutenberg.sh fetches and fast-forwards it to the latest trunk