Repository navigation
Maryna/monorepo - #237
Merged
Merged
Maryna/monorepo#237
Conversation
Move the Workers integration into its own package and store the required upstream Puppeteer changes as a patch.
Delete the checked-in upstream repository after moving it to the submodule. Reduce the root workspace to Cloudflare's Browser Run packages.
…peteer 24.40.0) compatibility improvements
…error response handling in Chromium navigation
…re for WebSocket transport
…ation with retry and binding parameters
…elease verification and upstream testing
…d alias configuration comments for Workers-compatible memfs exports
Refaerds
force-pushed
the
maryna/monorepo
branch
from
September 24, 2026 13:33
4f6646c to
fc23da2
Compare
…ion capability check and add test coverage for incomplete RPC bindings
…xy test title escaping, and validate Stagehand screenshot data URLs
…nabled for this repository
The Cloudflare playwright-mcp fork does not run this suite (its upstream CI workflow is disabled), and it exercises local Node browsers rather than the Workers wrapper. Drop test:upstream and the Chromium/Firefox installs; an in-Worker MCP suite against Browser Run will follow separately.
…ctions
The Workers-only check that replaces new Function treated `async (a) => a`
and `function (a) {}` as method shorthand and prefixed them with
`function `, producing a SyntaxError for almost every evaluate/click in
Worker builds. Classify arrows (including async ones with nested or
default parameters) and function/class expressions as already valid, and
prefix only real method shorthand.
keep_alive is an inactivity timeout, so a session with a connected browser stays open past it, as the spec on main expected. Check it through the per-session endpoint instead of the shared session list, and report the active-session count and limit when a new session is missing from limits.
…ions Check the test's own session through the per-session endpoint instead of comparing account-wide session lists, restore connected-session keep_alive semantics, and poll the limits endpoint with a diagnostic on failure.
Chromium replaces an empty 4xx navigation response with its own error page, so navigations to missing files ended on chrome-error://chromewebdata/. Return "File not found: <path>" like the upstream test server.
Poll the per-session endpoint briefly after acquiring, and wait keep_alive plus a margin for a released session to close.
…st Worker @cloudflare/playwright 0.0.11 reassembles binary CDP chunks from ArrayBuffer frames. From compatibility date 2026-03-17 Workers delivers binary frames as Blob (websocket_standard_binary_type), so no CDP response was ever parsed and browser_navigate timed out in connectOverCDP. Opt the test Worker out with no_websocket_standard_binary_type and document the flag for users on recent compatibility dates.
Proxy tests take their test list from the deployed Worker. A deploy takes a few seconds to propagate, so CI could read the previous version's list and then run IDs that the new version does not have (a renamed test failed in 43ms with no error). The test Workers now report their version in x-worker-version, the workflows export the ID printed by wrangler deploy, and the generators poll until that version serves the list.
The session details endpoint returns 200 for ended sessions too. After a browser crash, retries reconnected to the dead session and every later test in the worker failed with 410. Reuse a saved session only when it has no endTime or close reason.
Browser Run returns at most 200 active sessions under limits. On an account with more active sessions a new session can be cut off, so confirm it through the per-session endpoint when the list is full.
JSON.stringify already escapes the generated literals, so the extra replace() inserted a literal backslash into titles (CodeQL js/incomplete-sanitization, alerts 54/55). Match the Playwright generator and update the one skip entry that relied on the escaped title.
When Browser Run's browser for the shared test session dies (for example 410 "Browser not running (state: unhealthy)"), the Puppeteer test Worker retried the connect for 10s and then threw, so CI only saw a generic 1101 page, and the retry reconnected to the same dead session. Only retry connects that can recover (409 or no HTTP status), report connect and probe failures as a failed test with the real error, and mark such results sessionUnusable. The Playwright test Worker marks results whose errors show a 404/410 connect failure the same way. The proxy then drops the saved session so the retry acquires a new one.
…runtime Move the duplicated Node-side proxy harness (Browser Run session fixture, runTest, proxy spec generation with the deployed-version wait, file helpers) to @cloudflare/browser-test-runtime/proxy, and the Worker routing helpers (test list with x-worker-version, /v1 forwarding, unusable-session results) to @cloudflare/browser-test-runtime/worker-routes. Both are plain ES modules with no dependencies; the proxy module does not import @playwright/test, so each test project keeps its own version. Test server DOs, worker fixtures, worker test generation, and skip lists stay package-specific.
…all URLs per package Add repository and homepage fields for cloudflare/browser to all three packages, so npm and pkg.pr.new resolve this repository after the rename. Publish previews with --no-compact, because pkg.pr.new resolves compact URLs through the npm latest version's repository field, which still names the old repositories. Each preview workflow now posts its own pull request comment with the install URL and updates only that comment on new pushes and reruns.
|
npm i https://pkg.pr.new/cloudflare/puppeteer/@cloudflare/playwright-mcp@6f38dabf657ce1fa2f09f9e7efbaf749701f947fPublished by this workflow run. New pushes and reruns update this comment. |
|
npm i https://pkg.pr.new/cloudflare/puppeteer/@cloudflare/playwright@6f38dabf657ce1fa2f09f9e7efbaf749701f947fPublished by this workflow run. New pushes and reruns update this comment. |
|
npm i https://pkg.pr.new/cloudflare/puppeteer/@cloudflare/puppeteer@6f38dabf657ce1fa2f09f9e7efbaf749701f947fPublished by this workflow run. New pushes and reruns update this comment. |
The smoke test compared an exact byte percentage of the live example.com, which changes when that page or the browser changes. Use the JS and CSS coverage pages from the Puppeteer test assets, which the test Worker serves, with the same exact ranges as the upstream coverage specs.
Restore the main-branch behavior in both clients: connect through connectSession only for bindings that acquired the session with the RPC acquire method, and through the binding's fetch otherwise. A typeof check cannot detect the method, because every property of a Browser Run binding is an RPC stub, so a plain launch(env.BROWSER) called connectSession and failed where Browser Run does not serve it, for example in local development.
Declare launch, acquire and connectSession as methods, so that the BrowserRun type from @cloudflare/workers-types, whose options differ (for example, outboundByHost values typed as Fetcher), is assignable and launch(env.BROWSER) compiles without a cast. Drop readonly from the global Response.webSocket augmentation in Puppeteer to match workers-types; projects that load both failed with 'All declarations of webSocket must have identical modifiers' unless skipLibCheck was set. Add type tests in both packages against the real BrowserRun type from @cloudflare/workers-types under strict function types, so they follow the installed workers-types version. Exclude test-d from the Playwright tests tsconfig, which uses the generated worker configuration types; tsd checks it.
ruifigueira
reviewed
Oct 1, 2026
Refer to the global Browser Run types of the Workers runtime instead of copies that drifted from the binding (session timestamps, connection and outbound Worker types). Every Worker project loads them, from @cloudflare/workers-types or from wrangler types. - SessionGuardrails, AcquireResponse, ActiveSession, ClosedSession and LimitsResponse alias BrowserRunAcquireGuardrails, BrowserRunAcquireResult, BrowserRunSession and BrowserRunLimits. - BrowserWorker picks launch, acquire and connectSession from BrowserRun and still accepts fetch-only bindings such as service bindings. - outboundByHost takes the Fetcher values of BrowserRunAcquireOptions. - Remove the unreleased BrowserRunOptions, BrowserRunConnection, BrowserRunConnectOptions, BrowserRunTarget and BrowserRunAcquireResult exports, which shadowed the global names. Puppeteer builds with the DOM library, so a build-only declaration file defines the global names from the module form of @cloudflare/workers-types. It is not emitted, and the published declarations do not import the package. The types need @cloudflare/workers-types 5.20260917.1 or later, or Wrangler 4.134.0 or later for wrangler types; the READMEs say so. Regenerate the test Workers' types with wrangler types and add type tests for the aliases and fetch-only bindings.
Use the repository name after the planned rename for issue links, images, package links and the Deploy to Cloudflare buttons. The Stagehand and TodoMVC buttons pointed at the standalone cloudflare/playwright repository, which will be archived. The links work once cloudflare/puppeteer is renamed to cloudflare/browser.
The injected clock follows real time from injection until install(). On an open page, install() comes after at least two round trips to Browser Run. If they take more than 100 ms, the clock advances by one 100 ms step first, and performance.now() is 1101 instead of 1000.
Refaerds
marked this pull request as ready for review
October 12, 2026 09:07
The repository will be renamed to cloudflare/browser-run, not cloudflare/browser. Update the package repository and homepage fields, the README links and the Deploy to Cloudflare buttons.
Match the planned repository name. The root package is private and is not published.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR turns
cloudflare/puppeteerinto the monorepo for Cloudflare's Browser Run client libraries (BRAPI-404). It replaces the vendored Puppeteer fork with upstream submodules plus patches. It also brings@cloudflare/playwrightand@cloudflare/playwright-mcpinto this repository, so the three packages share one layout, one test harness, and one CI and release process.@cloudflare/puppeteer1.5.0-rc.0puppeteer-corev24.40.0@cloudflare/playwright1.3.7-next@cloudflare/playwright-mcp0.0.6-nextcloudflare/playwright-mcp@ee81e278)@cloudflare/browser-test-runtimeWhat kind of change does this PR introduce? Build, repository structure, and CI change. It also includes the Puppeteer upgrade to v24.40.0, the Playwright port.
Repository layout
patches/*.patch.npm run patchapplies them.npm run diffregenerates them from the submodules.npm run check:submodulesconfirms that the submodules are clean.git submodule update --init && npm ci && npm run build. SeeREADME.mdandRELEASING.md.What changes
Puppeteer (
@cloudflare/puppeteer)puppeteer-corev24.40.0 pluspatches/puppeteer.patch, instead of the vendored fork.launch,acquire,connectSession,outboundByHost, lab sessions, andkeep_alive→keepAlive.Unable to connect to browser: code: <status>: message: <body>(as Playwright does) instead of a null dereference.Playwright (
@cloudflare/playwright)cloudflare/playwright. It includes feat(cloudflare): support outbound workers in Browser Run playwright#228 (the same RPC features as Puppeteer).new Function()). Async arrows and anonymous functions were classified as method shorthand, which producedSyntaxError: Unexpected token '=>'.waitUntillifecycle, andrequest.sizes()resolves for failed responses.Playwright MCP (
@cloudflare/playwright-mcp)cloudflare/playwright-mcpfork: upstream v0.0.30 submodule, the fork's schema coercion patch, the fork's Worker wrapper and example, and ESM/CJS output.@cloudflare/playwright ^0.0.11on purpose. The fork'sfs→@cloudflare/playwright/fs(memfs) aliases require it, and current Playwright no longer exports that path. Moving to the workspace Playwright is a separate change.0.0.6-next, above the published0.0.5.test:remote). The test Worker setsno_websocket_standard_binary_type, because Playwright 0.0.11 expects ArrayBuffer WebSocket frames. From compatibility date 2026-03-17, Workers deliver them as Blob by default. The README has a "Compatibility date" section for users of the published package.Shared Worker test harness
Each package runs its upstream test suite inside a deployed test Worker against Browser Run. The Node Playwright runner sends each test to that Worker.
@cloudflare/browser-test-runtimehas two new entry points:/proxy(Node): Browser Run session fixture,runTest, and proxy spec generation./worker-routes(Worker): test list withx-worker-version,/v1forwarding to the binding, and unusable-session results.@playwright/test.wrangler deployand theCF_VERSION_METADATAbinding.limits().activeSessions.__cf_bmin cookie assertions.CI and release (
.github/workflows/cf_*)full,smoke(manual),prerelease(PR package preview), andpublish(release). There is alsocf_lockfile.yml.latest.latestandnext.contents: read(CodeQL).@cloudflare/workers-typesv5, and Vite floors^6.4.3/^7.3.6(security fixes). The remainingnpm auditfindings come fromagents@0.0.109, which MCP parity pins; that upgrade is deferred.Does this PR introduce a breaking change?
@cloudflare/puppeteermoves from1.4.xto1.5.0-rc.0onpuppeteer-core24.40.0, which includes the upstream API changes since the previous base.Did you add tests for your changes?
Yes:
Verification:
9db934a8: Puppeteer and Playwright full suites against Browser Run, MCP deploy and smoke, CodeQL, lockfile, and package validation.If relevant, did you update the documentation?
Yes: root
README.md,RELEASING.md(release procedure per package), the package READMEs, and the MCP example.Review guide
The diff has 2,000+ files, and most of it is the removal of the vendored Puppeteer tree (
docs/,website/,packages/puppeteer-core/,test/). Suggested order:README.md,RELEASING.md, rootpackage.json,scripts/patches/*.patch(the Cloudflare changes to upstream code)packages/*/src,index.d.ts, and package metadatapackages/*/testsandpackages/browser-test-runtime.github/workflows/cf_*.ymlOther information / follow-ups
agentsSDK upgrade and moving MCP to the workspace Playwright.state: unhealthy) and runs slowly. The harness now retries on a new session, but a few timing-sensitive upstream tests can still be flaky.