From f70647020b716e272aee41f6f183a6d35b286218 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 25 Jun 2026 10:30:27 +0200 Subject: [PATCH 1/2] ci(book): upload the Playwright report when the deploy job fails When there are test failures like in https://github.com/git/git-scm.com/actions/runs/28149818103, the Playwright report isn't uploaded. This is because upload-artifact step is guarded by if: always() && steps.playwright.outputs.result != '', but the Playwright step in the Action never wrote anything to $GITHUB_OUTPUT, so steps.playwright.outputs.result was always the empty string. This writes result=$PLAYWRIGHT_TEST_URL before running the tests to make the Playwright report upload. Assisted-by: Opus 4.8 Helped-by: Julia Evans Signed-off-by: Johannes Schindelin --- .github/actions/deploy-to-github-pages/action.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/actions/deploy-to-github-pages/action.yml b/.github/actions/deploy-to-github-pages/action.yml index 0c9ce9a856..a572044af0 100644 --- a/.github/actions/deploy-to-github-pages/action.yml +++ b/.github/actions/deploy-to-github-pages/action.yml @@ -298,7 +298,9 @@ runs: PLAYWRIGHT_TEST_URL: ${{ env.base_url }} # avoid test failures when HTTPS is enforced half-way through PLAYWRIGHT_EXTERNAL_HTTPS: ${{ inputs.external-https }} - run: npx playwright test --project=chrome + run: | + echo "result=$PLAYWRIGHT_TEST_URL" >>$GITHUB_OUTPUT && + npx playwright test --project=chrome - uses: actions/upload-artifact@v7 if: always() && steps.playwright.outputs.result != '' with: From 830490c6c65a7915b275c35b47eebcd74d2db4c8 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 25 Jun 2026 10:30:27 +0200 Subject: [PATCH 2/2] tests: retry the book redirect to dodge "chrome-error://chromewebdata/" The `book` Playwright test assert that `/book/` redirects to `/book/en/v2`. Occasionally this fails, landing on `chrome-error://chromewebdata/` instead, see e.g. https://github.com/git/git-scm.com/actions/runs/28149818103. This is a known Playwright/Chromium issue, see https://github.com/microsoft/playwright/issues/19161. Let's work around this (transient) problem by retrying multiple times. Assisted-by: Opus 4.8 Helped-by: Julia Evans Signed-off-by: Johannes Schindelin --- tests/git-scm.spec.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/tests/git-scm.spec.js b/tests/git-scm.spec.js index 5423d8b2b6..ef55128728 100644 --- a/tests/git-scm.spec.js +++ b/tests/git-scm.spec.js @@ -23,6 +23,23 @@ test.afterEach(async ({ page }, testInfo) => { if (process.platform === 'win32') test.setTimeout(60_000) // give it some time +// Navigating to a page that immediately redirects elsewhere via +// `` occasionally races with +// Chrome's navigation handling: the in-flight load is aborted and the page is +// left stranded on the internal error page `chrome-error://chromewebdata/`. +// As that is a committed navigation, merely polling for the target URL cannot +// recover from it, the navigation has to be re-triggered. This is a known, +// transient Playwright/Chromium issue (see e.g. +// https://github.com/microsoft/playwright/issues/19161), so retry the whole +// navigate-and-assert dance until the expected URL is reached. +async function gotoAndExpectRedirect(page, gotoURL, expectedURL) { + await expect(async () => { + await page.goto(gotoURL) + await expect(page).toHaveURL(expectedURL) + // Retry every second for up to 15 seconds in total + }).toPass({ intervals: [1_000], timeout: 15_000 }); +} + test('generator is Hugo', async ({page}) => { await page.goto(url) await expect(page.locator('meta[name="generator"]')).toHaveAttribute('content', /^Hugo /) @@ -189,11 +206,9 @@ test('anchor links in manual pages', async ({ page }) => { }) test('book', async ({ page }) => { - await page.goto(`${url}book/`) - await expect(page).toHaveURL(`${url}book/en/v2`) + await gotoAndExpectRedirect(page, `${url}book/`, `${url}book/en/v2`) - await page.goto(`${url}book`) - await expect(page).toHaveURL(`${url}book/en/v2`) + await gotoAndExpectRedirect(page, `${url}book`, `${url}book/en/v2`) // the repository URL is correct await expect(page.getByRole('link', { name: 'hosted on GitHub' }))