From a1bee5066d3799eeecdcc9e527dd74b72e847a6e Mon Sep 17 00:00:00 2001 From: Zachary Miller Date: Wed, 11 Nov 2026 09:29:59 -0500 Subject: [PATCH 1/2] Run the browser tests in parallel The tests spend their time waiting for pace's timers (restartOnRequestAfter, minTime, ghostTime) and for the requests they send, not on the CPU: one worker used about 17% of it. So every test now runs in parallel, also within a file, and CI uses one worker per CPU core instead of one in all. The tests share no state, and each worker has its own local server. --- playwright.config.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/playwright.config.mjs b/playwright.config.mjs index 53e8c8f..ae0fa91 100644 --- a/playwright.config.mjs +++ b/playwright.config.mjs @@ -15,7 +15,10 @@ const filesByBrowser = { chromium: ['pace.js', 'pace.min.js'], firefox: ['pace.m export default defineConfig({ testDir: 'tests', forbidOnly: CI, - workers: CI ? 1 : undefined, + // The tests spend their time waiting for pace's timers and their own requests, not on the + // CPU, so they run in parallel, also within a file; on CI, one worker per CPU core. + fullyParallel: true, + workers: CI ? '100%' : undefined, reporter: CI ? [['github'], ['list']] : 'list', projects: browsers.flatMap((browser) => filesByBrowser[browser].map((paceFile) => ({ From 209463d06c49e1b1a7a40a5ed3bc75f0a2f2879c Mon Sep 17 00:00:00 2001 From: Zachary Miller Date: Wed, 11 Nov 2026 13:05:45 -0500 Subject: [PATCH 2/2] Run the browser tests in Playwright's container image Each browser job installed its browser and the system packages it needs from Ubuntu's servers, which took 1.5 to 2.5 minutes and sometimes hung until the job's time limit. The jobs now run in Playwright's own image (mcr.microsoft.com/playwright, the setup Playwright's CI docs describe), which has both, so a job starts testing after about 20 seconds. The image is pinned to the version of @playwright/test and by digest, and the job's time limit drops from 10 to 5 minutes. --- .github/workflows/checks.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 74a053b..97fe366 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -35,7 +35,14 @@ jobs: browser-projects: name: browser-tests (${{ matrix.browser }} ${{ matrix.file }}) runs-on: ubuntu-26.04 - timeout-minutes: 10 + timeout-minutes: 5 + # Playwright's image comes with its browsers and the system packages they need + # (https://playwright.dev/docs/ci#via-containers), so nothing is installed here. + # Its version must match @playwright/test in package.json, or the tests fail + # to find their browsers. Pinned by digest, like the actions in actions.lock. + container: + image: mcr.microsoft.com/playwright:v1.64.1-noble@sha256:2f05f8a734509a7b3f26a912639488ee08f58a7b292d14d62271bcff9038768f + options: --user 1001 strategy: fail-fast: false # report every project matrix: @@ -56,10 +63,6 @@ jobs: - run: npm ci - # Not cached: Playwright's docs say restoring takes about as long as downloading. - - name: Install the browser - run: npx playwright install --with-deps --only-shell ${{ matrix.browser }} - - run: npm run test:browsers -- --project="${{ matrix.browser }} ${{ matrix.file }}" # The required check: passes only if every project passed, so the required