Skip to content

fix: migrate to github.com/mxschmitt/playwright-go v0.6100.0 - #228

Merged
Bluebugs merged 4 commits into
mainfrom
fix/ci-driver-cdn-and-dependabot
Aug 12, 2026
Merged

fix: migrate to github.com/mxschmitt/playwright-go v0.6100.0#228
Bluebugs merged 4 commits into
mainfrom
fix/ci-driver-cdn-and-dependabot

Conversation

@Bluebugs

@Bluebugs Bluebugs commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Root cause

Dependabot's weekly run and every PR's CI were failing for the same underlying reason: we were pinned to a playwright-go release published under a module path that no longer exists.

1. Dependabot aborts every gomod run (failing run)

The playwright-community GitHub org is archived; playwright-go moved back to github.com/mxschmitt/playwright-go (upstream #619). v0.6100.0 is the first release under the new path, and its go.mod declares that path. Resolving it through the old path fails:

module declares its path as: github.com/mxschmitt/playwright-go
        but was required as: github.com/playwright-community/playwright-go

Dependabot surfaces this as go_module_path_mismatch and exits non-zero for the whole run, not just for playwright-go — which is why the run was red every week even though the goproxy and testcontainers PRs were created fine. Upstream tracks the same symptom in #624.

Note that GitHub's repo redirect does still work, and every release up to v0.6000.0 still resolves through the old path. A redirect can't help here: Go verifies the module line inside the downloaded go.mod, which is exactly what stops a redirect from silently substituting a different module.

2. Every PR's CI fails

Staying on v0.5700.1 had an independent consequence. That release downloads the driver from the *.azureedge.net mirrors, retired along with the Azure CDN from Edgio, which now 404 for every driver version:

could not download driver: error: got non 200 status code: 404 (404 Not Found)
  from https://playwright.azureedge.net/builds/driver/playwright-1.57.0-linux.zip

The Playwright version step obtained the version by running the upstream CLI, which downloads that driver first. Because the failing command sat inside echo "version="$(...), its exit status was discarded and the step wrote an empty version, surfacing two steps later as an unrelated-looking error:

ERROR: failed to build: mcr.microsoft.com/playwright:v: not found

v0.6100.0 assembles the driver from npm + nodejs.org instead of the dead CDN (upstream #615), so the migration fixes this too.

Two follow-on breakages the upgrade exposed

Moving to Playwright 1.61.1 surfaced two more problems, both fixed here.

Browser servers became unreachable. Playwright 1.61 hardened WSServer.listen with hostname ??= "localhost"; 1.57 passed the hostname through to net.Server.listen, which binds all interfaces. Inside the container that means launchServer listens only on loopback and Docker's published port has nothing to forward to. It showed up twice removed from the cause — first could not get chromium port: timeout ... could not connect to http://localhost:32772, then listen EADDRINUSE: address already in use ::1:1027 once a second exec tried to start the same browser while the first unreachable server still held the port. Fixed by passing host: '0.0.0.0' explicitly, so the bind no longer depends on an upstream default.

The image tag no longer resolved. The tag was reverse-engineered from the Playwright CLI version, assuming playwright-go tags v0.{minor}{patch}.{n} for CLI 1.{minor}.{patch}. That held for 13 consecutive releases and then broke: v0.6100.0 ships CLI 1.61.1, which the convention would have written as v0.6101.0. We publish images for the v0.6100 line, so the derived tag names an image that does not exist.

Replaced with versions the Go toolchain already recorded — a consumer's own pinned playwright-ci-go version is the image tag, and failing that, playwright-go's module version gives the release line exactly. No convention to reverse-engineer.

That path only worked once a latent bug was fixed: getPlaywrightCIGoFromBuildInfo read if info, ok := debug.ReadBuildInfo(); !ok, running the lookup only when build info was absent — so it always reported failure, and would have dereferenced a nil *BuildInfo had it ever entered. Test_BuildInfoPath asserted the broken result, which is why it went unnoticed; go list was silently carrying the whole feature. With it fixed, go list is a fallback for in-repo development rather than the only working strategy.

Since neither strategy guesses, an unresolvable tag is now an error naming WithRepository rather than a docker pull for a tag that never existed.

Changes

  • Migrate the module path and all imports to github.com/mxschmitt/playwright-go, bumped to v0.6100.0 (Playwright CLI 1.57.0 → 1.61.1). The archived path is still recognised when resolving versions, so consumers mid-migration keep working.
  • Read the pinned CLI version from playwright-go via a small internal/cmd/playwrightversion helper instead of running the upstream CLI, so a metadata lookup no longer needs a CDN. Plus set -euo pipefail and an empty-value guard in the version step of ci.yml and main.yml.
  • host: '0.0.0.0' on launchServer in chromium.js / firefox.js / webkit.js.
  • Resolve the image tag from module versions; fix the inverted build-info guard; drop the CLI-version formula and the v0.5101.0 workaround that went with it.
  • Refresh testdata/screenshot-webkit.png for WebKit's rendering changes, following the same procedure the Dependabot workflow uses (both failed captures were byte-identical before promoting).

No Dependabot ignore rule is needed: once the old path is gone from go.mod, there is nothing left that fails to resolve.

Verification

Run locally against a Docker image built from this branch (PLAYWRIGHT_VERSION=1.61.1):

  • Full test suite green, including the Docker-backed browser tests — 24 unit tests plus Test_HelloWorld and Test_OverlapLifecycle on chromium and webkit.
  • examples green with no PLAYWRIGHTCI_* overrides, which exercises tag resolution end to end: it resolved v0.6100.0 on its own and pulled the matching image.
  • Driver install verified against v0.6100.0 on a machine where every azureedge mirror 404s — succeeds in ~7s.
  • go build ./..., go vet ./..., gofmt -l ., golangci-lint run — all clean.
  • The bind and tag-convention findings were confirmed against the extracted playwright-core 1.57.0 and 1.61.1 packages and all 14 playwright-go releases, not inferred from the symptom.

🤖 Generated with Claude Code

The playwright-community GitHub org is archived and playwright-go moved
back to github.com/mxschmitt/playwright-go. v0.6100.0 is the first
release published under the new module path, and its go.mod declares
that path — so resolving it through the old path fails:

    module declares its path as: github.com/mxschmitt/playwright-go
            but was required as: github.com/playwright-community/playwright-go

Dependabot reports this as go_module_path_mismatch and aborts the entire
update run, which is why every gomod update has been failing and no
playwright-go bump ever landed.

Staying on v0.5700.1 also left CI broken independently: that release
fetches the driver from the *.azureedge.net mirrors, which were retired
with the Azure CDN from Edgio and now 404 for every driver version. The
"Playwright version" step swallowed that failure and emitted an empty
version, so the image build failed far from the cause with
"mcr.microsoft.com/playwright:v: not found". v0.6100.0 assembles the
driver from npm and nodejs.org instead, so the download works again.

Also harden the version detection itself: read the pinned CLI version
straight out of playwright-go instead of running the upstream CLI (which
downloads the whole driver just to print a string), and fail the step
loudly when either version comes back empty.

getPlaywrightCIGoFromBuildInfo keeps recognising the old module path so
consumers mid-migration still resolve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 11, 2026 22:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the project from the archived github.com/playwright-community/playwright-go module path to github.com/mxschmitt/playwright-go at v0.6100.0, addressing Dependabot module path mismatch failures and the retired Azure CDN driver download failures. It also updates CI to determine the Playwright CLI version without invoking the upstream Playwright CLI command.

Changes:

  • Bump and migrate Playwright Go dependency/imports to github.com/mxschmitt/playwright-go v0.6100.0.
  • Add a small helper (internal/cmd/playwrightversion) and update workflows to read the pinned Playwright CLI version via Go code.
  • Harden CI version-detection steps with set -euo pipefail and explicit empty-value guards.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Updates Playwright-Go link to the new upstream module org/path.
go.mod Switches required module to github.com/mxschmitt/playwright-go v0.6100.0.
go.sum Removes old module checksums and adds new ones for mxschmitt/playwright-go.
install.go Migrates import path used by installation logic.
browsers.go Migrates import path for browser API surface.
container.go Updates module detection to prefer mxschmitt path while retaining fallback for legacy consumers.
playwrightci_test.go Updates tests to import the new module path.
benchmark_test.go Updates benchmarks to import the new module path.
examples/example_test.go Updates examples to import the new module path.
internal/cmd/playwrightversion/main.go New helper to print the pinned Playwright CLI version without running upstream CLI.
.github/workflows/ci.yml Uses helper + strict shell settings to reliably compute Playwright versions.
.github/workflows/main.yml Same Playwright version computation for release/tag pipeline.
.github/workflows/pr.yml Updates Dependabot/Playwright-Go conditional checks to match the new module path.
CLAUDE.md Updates documentation reference to the new Playwright-Go module path.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 41 to +45
- name: Playwright version
id: playwright
run: |
export PLAYWRIGHT_GO_VERSION=$(go list -m all | grep github.com/playwright-community/playwright-go | awk '{print $2}')
set -euo pipefail
PLAYWRIGHT_GO_VERSION=$(go list -m -f '{{.Version}}' github.com/mxschmitt/playwright-go)
Bluebugs and others added 2 commits August 11, 2026 16:51
Playwright 1.61 hardened its WebSocket server: WSServer.listen now does
`hostname ??= "localhost"`, where 1.57 passed the hostname straight
through to net.Server.listen and so bound every interface by default.

Inside the browser container that means launchServer only listens on
loopback, and Docker's published port has nothing to forward to. The
symptom is two steps removed from the cause:

    could not get chromium port: timeout, could not connect to browser
      container: could not connect to http://localhost:32772

and then, once a second exec tries to start the same browser while the
first unreachable server is still holding the port:

    Error: listen EADDRINUSE: address already in use ::1:1027

Pass host: '0.0.0.0' explicitly so the bind no longer depends on an
upstream default.

WebKit's rendering changed between Playwright 1.57.0 and 1.61.1, so
refresh its reference screenshot the same way the Dependabot workflow
would have: both failed captures were byte-identical before promoting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The image tag was reverse-engineered from the Playwright CLI version, on
the convention that playwright-go tags v0.{minor}{patch}.{n} for CLI
1.{minor}.{patch}. That held for 13 consecutive releases and then broke:
v0.6100.0 ships CLI 1.61.1, which the convention would have written as
v0.6101.0. We publish images for the v0.6100 line, so the derived tag
now names an image that does not exist.

Read the versions the Go toolchain already recorded instead. A consumer's
own pinned playwright-ci-go version *is* the image tag; failing that, the
playwright-go module version gives the release line exactly, with no
convention to reverse-engineer.

That path only works because getPlaywrightCIGoFromBuildInfo was broken:
`if info, ok := debug.ReadBuildInfo(); !ok` ran the lookup only when
build info was absent, so it always reported failure — and would have
dereferenced a nil *BuildInfo if it ever had entered. Test_BuildInfoPath
asserted the broken result, which is why it went unnoticed. With it
fixed, go list is a fallback for developing in this repository rather
than the only working strategy.

Since neither strategy guesses, there is nothing sensible left to guess
with, so an unresolvable tag is now an error naming WithRepository
instead of a docker pull for a tag that never existed. The v0.5101.0
workaround goes with the formula that needed it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 11, 2026 22:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 21 changed files in this pull request and generated no new comments.

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Golang test coverage difference report

Coverage increased by 3.04%. 🏅 Keep it up 🏅

Package report
package                                                                            before    after    delta
-------                                                                           -------  -------  -------
github.com/mountain-reverie/playwright-ci-go                                       73.85%   76.89%   +3.04%
                                                                          total:   73.85%   76.89%   +3.04%

The tag job runs go list and go run straight after checkout, with no
actions/setup-go step, so it uses whatever Go the runner image happens
to ship. That is older than the go directive in our go.mod today: the
last successful release run logged

    go: downloading go1.25.0 (linux/amd64)

meaning the job silently depended on toolchain auto-download to work at
all. That only holds while GOTOOLCHAIN stays at its default, and it
tracks a runner image default that moves without notice.

Pin it the way ci.yml already does. setup-go also sets GOTOOLCHAIN=local,
so the resolved version becomes authoritative instead of a starting
point for a download.

Reported by Copilot on #228.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 12, 2026 00:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 21 changed files in this pull request and generated no new comments.

Suppressed comments (2)

imagetag_test.go:111

  • Same issue here: the parallel subtest closes over the reused range variable test, which can cause cases to mix when t.Parallel() runs them concurrently. Shadow test := test inside the loop.
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()

			got, ok := versionFromBuildInfo(test.info, true)
			assert.Equal(t, test.ok, ok)
			assert.Equal(t, test.want, got)
		})

imagetag_test.go:36

  • The subtest captures the range variable test while calling t.Parallel(). In Go, the range variable is reused, so parallel subtests can read the wrong case values and become flaky. Shadow the loop variable inside the loop before starting the subtest.

This issue also appears on line 104 of the same file.

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()

			got, ok := playwrightGoTagLine(test.version)
			assert.Equal(t, test.ok, ok)
			assert.Equal(t, test.want, got)
		})

@Bluebugs
Bluebugs enabled auto-merge August 12, 2026 00:09
@Bluebugs
Bluebugs merged commit 5571fab into main Aug 12, 2026
9 checks passed
@Bluebugs
Bluebugs deleted the fix/ci-driver-cdn-and-dependabot branch August 12, 2026 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants