Skip to content

test(e2e): Add Bun, Deno and Cloudflare variants to react-router-8-framework - #24598

Draft
JPeer264 wants to merge 1 commit into
jp/node-suites-bun-buildfrom
jp/e2e-runtime-variants-poc
Draft

JPeer264 wants to merge 1 commit into
jp/node-suites-bun-buildfrom
jp/e2e-runtime-variants-poc

Conversation

@JPeer264

@JPeer264 JPeer264 commented Sep 22, 2026

Copy link
Copy Markdown
Member

POC for running one framework e2e app on several server runtimes instead of one app per runtime (Linear project P-JS-2537). react-router-8-framework now runs its full Playwright suite on Bun, Deno and Cloudflare (local workerd) as optional variants, next to the Node job.

A variant sets RUNTIME in a named script and playwright.config.mjs picks the start command from it. Bun and Deno reuse the Node build. Cloudflare builds with its own vite.cloudflare.config.ts (@cloudflare/vite-plugin + sentryCloudflareVitePlugin). React Router has no option to pick a server entry, so the new runtimeEntryPlugin from @sentry-internal/test-utils/vite loads entry.server.cloudflare.tsx in its place. A new runtime matrix key makes CI install Bun or Deno for a variant, so new variants need no build.yml change. The convention is in the e2e README. Tests branch on RUNTIME only where the runtimes are expected to differ: platform and sdk.name on Cloudflare, Express's trailing-slash redirect, and on Bun and Cloudflare the effects of having no instrumented Express layer (Express is not instrumented under bun run).

The Bun variant is based on the Bun auto-instrumentation PR below it, which fixes diagnostics channels being garbage collected on Bun and the missing http.server span.

Running the suite on the other runtimes surfaced SDK bugs, fixed here:

  • In a Worker, @sentry/react-router resolved to the browser build (browser comes before worker in the exports map), so Sentry.flush and Sentry.startSpan were undefined. It now resolves the Cloudflare entry under workerd.
  • Prerendered pages got a sentry-trace meta tag baked in at build time, because the prerender runs through the wrapped Worker. Every visitor of the static page then continued the same trace. Paths from the build's prerender list no longer get meta tags.
  • An index route has no path, so wrapSentryHandleRequest never named it. On Node, Express named the span first and hid this. An index route now takes its nearest ancestor's path, or /.
  • createSentryHandleError and lowQualityTransactionsFilterIntegration are runtime-agnostic but were only exported for Node.
  • @sentry/cloudflare never set a transaction name on the request scope, so errors thrown in a loader had no transaction.

Deno is pinned to v2.9.0: Deno 2.8 loses async context in socket callbacks, which drops ioredis spans that queue before the connection is ready. Deno 2.8 also crashed on the bare import "events" that force-bundled dependencies leave in the SSR output; those imports now get the node: prefix.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 29.23 kB - -
@sentry/browser - with treeshaking flags 27.49 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.4 kB - -
@sentry/browser (incl. Tracing) 51.16 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 51.17 kB - -
@sentry/browser (incl. Tracing, Profiling) 54.16 kB - -
@sentry/browser (incl. Tracing, Replay) 90.75 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 79.85 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 95.45 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 108.42 kB - -
@sentry/browser (incl. Feedback) 46.76 kB - -
@sentry/browser (incl. sendFeedback) 34.29 kB - -
@sentry/browser (incl. FeedbackAsync) 39.39 kB - -
@sentry/browser (incl. Metrics) 30.25 kB - -
@sentry/browser (incl. Logs) 30.5 kB - -
@sentry/browser (incl. Metrics & Logs) 31.16 kB - -
@sentry/react 30.98 kB - -
@sentry/react (incl. Tracing) 53.44 kB - -
@sentry/vue 36.72 kB - -
@sentry/vue (incl. Tracing) 53.69 kB - -
@sentry/svelte 29.25 kB - -
CDN Bundle 30.93 kB - -
CDN Bundle (incl. Tracing) 51.69 kB - -
CDN Bundle (incl. Logs, Metrics) 33.19 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 53.66 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 73.91 kB - -
CDN Bundle (incl. Tracing, Replay) 89.27 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 91.23 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 95.43 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 97.41 kB - -
CDN Bundle - uncompressed 91.4 kB - -
CDN Bundle (incl. Tracing) - uncompressed 153.76 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 97.97 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 159.72 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 227.54 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 273.49 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 279.43 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 287.2 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 293.13 kB - -
@sentry/nextjs (client) 55.78 kB - -
@sentry/sveltekit (client) 51.58 kB - -
@sentry/core/server 39.92 kB - -
@sentry/core/browser 13.63 kB - -
@sentry/node 134.17 kB +0.24% +316 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 82.57 kB +0.21% +172 B 🔺
@sentry/node - without tracing 90.72 kB +0.39% +352 B 🔺
@sentry/node - without channel injection 112.63 kB +0.22% +238 B 🔺
@sentry/aws-serverless 98.98 kB +0.31% +299 B 🔺
@sentry/cloudflare (withSentry) - minified 206.4 kB +0.02% +24 B 🔺
@sentry/cloudflare (withSentry) 513.54 kB +0.01% +48 B 🔺

View base workflow run

@JPeer264
JPeer264 force-pushed the jp/e2e-runtime-variants-poc branch from f08b065 to 9297a36 Compare September 23, 2026 05:27
@JPeer264 JPeer264 changed the title test(e2e): Add Bun, Deno and Cloudflare variants to react-router-8-framework test(e2e): Add Deno and Cloudflare variants to react-router-8-framework Sep 23, 2026
@JPeer264
JPeer264 force-pushed the jp/e2e-runtime-variants-poc branch 2 times, most recently from d358a6c to 4dd044c Compare September 23, 2026 09:12
@JPeer264
JPeer264 removed this pull request from stack #24600 September 23, 2026 09:14
@JPeer264 JPeer264 changed the title test(e2e): Add Deno and Cloudflare variants to react-router-8-framework test(e2e): Add Bun, Deno and Cloudflare variants to react-router-8-framework Sep 23, 2026
@JPeer264
JPeer264 changed the base branch from develop to jp/node-suites-bun-build September 23, 2026 09:15
@JPeer264
JPeer264 added this pull request to stack #24613 September 23, 2026 09:15
@JPeer264
JPeer264 removed this pull request from stack #24613 September 23, 2026 09:51
@JPeer264
JPeer264 added this pull request to stack #24633 September 23, 2026 09:51
@JPeer264
JPeer264 force-pushed the jp/e2e-runtime-variants-poc branch 2 times, most recently from adb5cb1 to fb48ca5 Compare September 23, 2026 10:02
@JPeer264
JPeer264 force-pushed the jp/e2e-runtime-variants-poc branch 2 times, most recently from 51e4c78 to b94af9d Compare September 23, 2026 12:21
@JPeer264
JPeer264 force-pushed the jp/e2e-runtime-variants-poc branch from b94af9d to 6e3b225 Compare September 23, 2026 12:24
@JPeer264
JPeer264 force-pushed the jp/e2e-runtime-variants-poc branch from 6e3b225 to c2638e4 Compare September 23, 2026 13:23
Comment on lines +1195 to +1199
- name: Set up Bun
if: matrix.runtime == 'bun'
uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3.14'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Mutable oven-sh/setup-bun@v2 in secrets-bearing optional E2E job

The new Bun setup step uses third-party oven-sh/setup-bun@v2 (mutable tag) in a job that already has E2E and Cloudflare secrets; pin it to a full commit SHA like other third-party actions in this workflow.

Evidence
  • The optional E2E job env exposes secrets.E2E_TEST_AUTH_TOKEN, secrets.E2E_TEST_DSN, secrets.E2E_OPENROUTER_API_KEY, secrets.CLOUDFLARE_API_TOKEN, and secrets.CLOUDFLARE_ACCOUNT_ID.
  • The changed step runs uses: oven-sh/setup-bun@v2 when matrix.runtime == 'bun', so that action executes in the same privileged job.
  • @v2 is a movable tag, not a 40-character commit SHA; a tag rewrite could run attacker-controlled code with those secrets available.
  • Nearby first-party/third-party setup already shows the safer pattern (pnpm/action-setup@0977fd9...).

Identified by Warden · security-review · V7R-HVR

…amework

Runs the same Playwright suite on Bun, Deno and Cloudflare (local workerd)
as optional variants of the existing app, instead of one app per runtime.
A variant can set a `runtime` matrix key (`bun` or `deno`), and CI then
installs that runtime for the job. The Cloudflare build uses its own Vite
config with `@cloudflare/vite-plugin` and `sentryCloudflareVitePlugin`,
and swaps in a workerd server entry with the new `runtimeEntryPlugin`
from `@sentry-internal/test-utils/vite`.

Getting the variants green needed these SDK fixes:

- react-router: resolve the Cloudflare entry under the `workerd`
  condition, so `Sentry.flush` and `Sentry.startSpan` exist in a Worker.
- react-router: export `createSentryHandleError` and
  `lowQualityTransactionsFilterIntegration` from `/cloudflare`.
- react-router: do not write trace meta tags into prerendered pages, which
  otherwise pinned every visitor of the static page to one build-time trace.
- react-router: name an index route after its nearest ancestor path, or
  `/`. It has no `path` of its own, so without an Express layer (Bun,
  Cloudflare) the index page got no route name.
- cloudflare: set the request as the transaction name, like Node does.
- server-utils: write bare builtin imports of force-bundled dependencies
  with the `node:` prefix, which Deno before 2.9 needs.

Under `bun run` Express is not instrumented, so on Bun (as on Cloudflare)
the error transaction stays the request path and the meta tag names the
http.server segment. The Bun variant relies on the diagnostics channel
fixes of the Bun auto-instrumentation suites PR it is based on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JPeer264
JPeer264 force-pushed the jp/e2e-runtime-variants-poc branch from c2638e4 to 90bb70c Compare September 23, 2026 13:31

This branch has not been deployed

No deployments
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.

1 participant