Skip to content

test(e2e): Run nestjs-12 on Bun, Deno and Cloudflare - #26283

Merged
isaacs merged 4 commits into
developfrom
feat/nestjs-12-runtime-variants
Nov 12, 2026
Merged

isaacs merged 4 commits into
developfrom
feat/nestjs-12-runtime-variants

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Why: Runs the nestjs-12 suite on Bun, Deno and Cloudflare (local workerd) as optional variants next to the required Node job, with the runtime variant setup from #24598. Each runtime inits its own SDK (@sentry/bun, @sentry/deno with --preload=@sentry/deno/import, @sentry/cloudflare via instrument.server.ts) and adds nestIntegration() from @sentry/nestjs. New tests cover parameterized route names, per-request isolation, incoming trace continuation, outgoing fetch with sentry-trace/baggage, and logs. They pass on all four runtimes with no RUNTIME branches. All four variants are green locally through pnpm run test:run nestjs-12 [--variant …].

Decisions that are hard to see in the diff:

  • Bun bundles the nest build output with @sentry/bun/plugin (bun run gets no diagnostics channel injection, see test(bun): Run the auto-instrumentation suites with bundled scenarios #24612). The variant pins Bun 1.4.4, because Bun 1.3.14 renames classes in bundles (let X = class X {} becomes class X2). Nest span names come from class names, so 6 span tests fail on 1.3.14 (ExampleMiddleware2, ParseIntPipe2). To allow the pin, prepare-e2e-test gets a bun-version input that works like deno-version.
  • Cloudflare bundles the same nest build output (tsc emits the decorator metadata Nest DI needs) with Vite 8. Rollup in Vite 7 renames the classes the same way. Nest boots in the first request through httpServerHandler from cloudflare:node.
  • Expected differences branch on RUNTIME, each with a comment: the SDK name; no http.response.status_text on Bun, because Bun's node:http leaves statusMessage unset; the http.server span attributes on Cloudflare, which withSentry builds from the Request; and the two cron tests on Cloudflare, which are skipped because workerd runs no timers outside a request, so @nestjs/schedule jobs never fire.
  • On current develop, the Deno audit findings (broken route names, broken outgoing fetch) no longer happen, and Cloudflare errors arrive through SentryGlobalFilter. The Sept 2026 audit's db-span findings don't apply here because nestjs-12 has no database.

How to review: Start with nestjs-12/package.json (variants, scripts), then bun-build.mjs, workers/app.ts, and the RUNTIME branches in tests/spans.test.ts.

Unsure about: The variants start optional, and these SDK defects are still open, so this PR only refs #24844. The RUNTIME branches in tests/spans.test.ts call them out as known defects:

  • getHttpSpanDetailsFromUrlObject (core) sets url.scheme with a trailing colon (http:) and url.port as a string, on Cloudflare, Bun.serve and Nitro server spans. fix(core): Set url.scheme without colon and url.port as a number #26284 fixes that. The Cloudflare http.server span also has no sentry.kind or http.response.status_text, which nothing tracks yet.
  • Bun's node:http leaves res.statusMessage unset, so Bun http.server spans have no http.response.status_text. The SDK could fall back to the standard reason phrase. Not filed yet.
  • The CI default Bun is still 1.3.14, which renames bundled classes. Make Bun 1.4.x the default for E2E test apps #26289 proposes making 1.4.x the default, which would remove the per-variant bun-version input but could change other Bun apps' results.

Refs #24844

via Isaac Schlueter.

--

View Session [Sentry]

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Optional E2E tests

Some optional checks were not successful. They do not block the merge. 4 not successful, 56 successful. See the run.

Check Status
❌ CI: Optional E2E Tests / E2E nextjs-16-cacheComponents (cloudflare) Test (optional) Failing after 10m Details
❌ CI: Optional E2E Tests / E2E node-eve (orchestrion) Test (optional) Failing after 2m Details
❌ CI: Optional E2E Tests / E2E node-eve Test (optional) Failing after 2m Details
❌ CI: Optional E2E Tests / E2E node-eve (latest) Test (optional) Failing after 52s Details
Successful checks
Check Status
✅ CI: Optional E2E Tests / E2E astro-7 Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries (cloudflare) Test (optional) Successful in 46s Details
✅ CI: Optional E2E Tests / E2E nestjs-12 (bun) Test (optional) Successful in 54s Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (vinext) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E cloudflare-mastra Test (optional) Successful in 45s Details
✅ CI: Optional E2E Tests / E2E cloudflare-agent Test (optional) Successful in 36s Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries Test (optional) Successful in 46s Details
✅ CI: Optional E2E Tests / E2E nextjs-14 (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-fastify-6 (tracer provider) Test (optional) Successful in 42s Details
✅ CI: Optional E2E Tests / E2E node-express-send-to-sentry Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E gen-ai-libraries (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E cloudflare-workers-send-to-sentry Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (cloudflare, latest) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E cloudflare-think (ai v6) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E deno (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-express-mcp-v2 Test (optional) Successful in 36s Details
✅ CI: Optional E2E Tests / E2E cloudflare-think Test (optional) Successful in 55s Details
✅ CI: Optional E2E Tests / E2E node-express-send-to-sentry-static Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nestjs-12 (latest) Test (optional) Successful in 53s Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (vinext, bun) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E cloudflare-flue-send-to-sentry Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nestjs-12 (cloudflare) Test (optional) Successful in 33s Details
✅ CI: Optional E2E Tests / E2E debug-id-sourcemaps Test (optional) Successful in 44s Details
✅ CI: Optional E2E Tests / E2E astro-7-static Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nextjs-15 (turbo) Test (optional) Successful in 3m Details
✅ CI: Optional E2E Tests / E2E cloudflare-pi-durable Test (optional) Successful in 50s Details
✅ CI: Optional E2E Tests / E2E nextjs-16-tunnel (cloudflare) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-flue Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E cloudflare-pi-durable (latest) Test (optional) Successful in 51s Details
✅ CI: Optional E2E Tests / E2E node-openai-decisions Test (optional) Successful in 32s Details
✅ CI: Optional E2E Tests / E2E node-flue (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react-cloudflare Test (optional) Successful in 38s Details
✅ CI: Optional E2E Tests / E2E nuxt-5 Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nextjs-16 (deno) Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nextjs-15 (latest) Test (optional) Successful in 4m Details
✅ CI: Optional E2E Tests / E2E nuxt-5-cloudflare Test (optional) Successful in 37s Details
✅ CI: Optional E2E Tests / E2E nuxt-5 (tunnel-dev) Test (optional) Successful in 57s Details
✅ CI: Optional E2E Tests / E2E node-mastra (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-express-mcp-v1 Test (optional) Successful in 33s Details
✅ CI: Optional E2E Tests / E2E node-pi-durable Test (optional) Successful in 37s Details
✅ CI: Optional E2E Tests / E2E solidstart-2 Test (optional) Successful in 51s Details
✅ CI: Optional E2E Tests / E2E nextjs-orpc Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-pi-durable (latest) Test (optional) Successful in 36s Details
✅ CI: Optional E2E Tests / E2E react-router-7-framework-instrumentation Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react (latest) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E node-fastify-6 Test (optional) Successful in 36s Details
✅ CI: Optional E2E Tests / E2E node-openai-decisions (latest) Test (optional) Successful in 32s Details
✅ CI: Optional E2E Tests / E2E node-mastra Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E react-send-to-sentry Test (optional) Successful in 2m Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps (client source maps kept) Test (optional) Successful in 37s Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps (static / nuxt generate) Test (optional) Successful in 42s Details
✅ CI: Optional E2E Tests / E2E tanstackstart-react-sourcemaps Test (optional) Successful in 31s Details
✅ CI: Optional E2E Tests / E2E vue-3 (no Options API) Test (optional) Successful in 1m Details
✅ CI: Optional E2E Tests / E2E nuxt-5-sourcemaps Test (optional) Successful in 42s Details
✅ CI: Optional E2E Tests / E2E nestjs-12 (deno) Test (optional) Successful in 59s Details
✅ CI: Optional E2E Tests / E2E supabase-nextjs Test (optional) Successful in 2m Details

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Compared: 439a5df (PR test merge using develop at edae47f)

Against: edae47f (develop) · base run #65716

✅ Baseline matches: this diff contains only this PR's changes.

Path Size % Change Change
@sentry/browser 29.98 kB - -
@sentry/browser - with treeshaking flags 28.13 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 28.02 kB - -
@sentry/browser (incl. Tracing) 52.36 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 52.36 kB - -
@sentry/browser (incl. Tracing, Profiling) 55.33 kB - -
@sentry/browser (incl. Tracing, Replay) 92.76 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 81.41 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 97.49 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 110.48 kB - -
@sentry/browser (incl. Feedback) 47.57 kB - -
@sentry/browser (incl. sendFeedback) 35.07 kB - -
@sentry/browser (incl. FeedbackAsync) 40.18 kB - -
@sentry/browser (incl. Metrics) 31.54 kB - -
@sentry/browser (incl. Logs) 31.83 kB - -
@sentry/browser (incl. Metrics & Logs) 32.52 kB - -
@sentry/react 31.84 kB - -
@sentry/react (incl. Tracing) 54.8 kB - -
@sentry/vue 38.39 kB - -
@sentry/vue (incl. Tracing) 55.38 kB - -
@sentry/svelte 30 kB - -
@sentry/remix (Remix 3 client bundle) 57.97 kB - -
CDN Bundle 31.77 kB - -
CDN Bundle (incl. Tracing) 52.94 kB - -
CDN Bundle (incl. Logs, Metrics) 34.58 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 55.45 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 76.05 kB - -
CDN Bundle (incl. Tracing, Replay) 91.22 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 93.77 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 97.34 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 99.93 kB - -
CDN Bundle - uncompressed 92.89 kB - -
CDN Bundle (incl. Tracing) - uncompressed 156.15 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 101.42 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 163.92 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 233.31 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 278.17 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 285.93 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 291.87 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 299.63 kB - -
@sentry/nextjs (client) 57.74 kB - -
@sentry/sveltekit (client) 52.88 kB - -
@sentry/core/server 44.51 kB - -
@sentry/core/browser 14.02 kB - -
@sentry/node 157.81 kB +0.01% +15 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 82.31 kB - -
@sentry/node - without tracing 97.24 kB +0.02% +19 B 🔺
@sentry/node - without channel injection 138.13 kB +0.02% +19 B 🔺
@sentry/aws-serverless 106.09 kB +0.03% +24 B 🔺
@sentry/cloudflare (withSentry) - minified 204.45 kB - -
@sentry/cloudflare (withSentry) 508.11 kB - -
@sentry/nextjs/cloudflare (withSentry) - minified 229.47 kB - -

View base workflow run

@isaacs isaacs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Main concern is re the PR description.

#24844 says it is done when "every variant is green and required, or this issue records why a runtime is not supported", and "SDK defects the variants surface are fixed here, or split into their own issue". This PR adds the variants as optional, and the description lists three follow-ups as "not filed". If this merges as-is, the issue closes, and nothing tracks the follow-ups or the move to required variants.

Suggestion: change to "Refs #24844" (or "Refs"), or file the follow-ups first and link them. Then the RUNTIME branches in spans.test.ts can point at those issues, so whoever fixes them knows to remove the branches.

The follow-ups:

  • Cloudflare / Bun.serve / Nitro http.server spans use url.scheme: 'http:' (with a colon) and string url.port. Node uses url.scheme: 'http' and integer server.port. The Cloudflare span also has no sentry.kind or http.response.status_text. (#26284)
  • The CI default Bun (1.3.14) renames classes in bundles, so we should upgrade that to 1.4 (to be filed).

sentry-junior Bot and others added 4 commits November 11, 2026 15:28
`nestjs-12` now runs its suite on Bun, Deno and Cloudflare (local
workerd) as optional variants, next to the required Node job, following
the runtime variant setup of `react-router-8-framework`. Each runtime
inits its own SDK and adds `nestIntegration()` from `@sentry/nestjs`.

Bun bundles the `nest build` output with `@sentry/bun/plugin`, because
`bun run` gets no diagnostics channel injection. The variant pins Bun
1.4.4: Bun 1.3 renames classes in bundles (`ExampleMiddleware2`), which
breaks span names taken from class names. Variants can now set
`bun-version` like `deno-version`. Cloudflare bundles the same output
with Vite 8 (Rollup in Vite 7 renames classes the same way) and boots
Nest in the first request through `httpServerHandler`.

New tests cover parameterized route names, per-request isolation,
incoming trace continuation, outgoing `fetch` propagation and logs on
every runtime. Expected differences branch on `RUNTIME`: the SDK name,
`http.response.status_text` on Bun, the attributes of the Cloudflare
`http.server` span, and the cron tests on Cloudflare, where workerd runs
no timers outside a request.

Refs #24844

Co-Authored-By: Isaac Schlueter <isaac.schlueter@sentry.io>
Mark the Cloudflare and Bun `RUNTIME` branches as known defects, so a
later SDK fix doesn't look like a regression. Let the Workers app retry
Nest's bootstrap after a failure. Compare the `sentry-trace` header as a
string. Explain why each package in the Bun build stays external.
Co-Authored-By: Isaac Schlueter <isaac.schlueter@sentry.io>
@isaacs
isaacs force-pushed the feat/nestjs-12-runtime-variants branch from fa6375a to 35af7eb Compare November 11, 2026 14:28
@isaacs
isaacs enabled stacked auto-merge (squash) November 11, 2026 14:28
@isaacs
isaacs merged commit 8832e97 into develop Nov 12, 2026
1189 of 1199 checks passed
@isaacs
isaacs deleted the feat/nestjs-12-runtime-variants branch November 12, 2026 08:53
isaacs added a commit that referenced this pull request Nov 12, 2026
…26284)

**Why:** `getHttpSpanDetailsFromUrlObject` copied `URL.protocol` and
`URL.port` as they are, so spans got `url.scheme: 'https:'` and
`url.port: '8080'` (a string). The Sentry conventions define
`url.scheme` as the bare scheme (example `"https"`) and `url.port` as a
number. Node `http.server` spans already send `url.scheme: 'http'` and
an integer port. The helper builds the HTTP spans of Cloudflare
`withSentry`, `Bun.serve`, Deno, Nitro and outgoing Node `http`
requests, so their values change too: streamed `url.port` becomes `type:
'integer'`. The attribute keys stay the same, but saved queries on the
old values stop matching, so the changelog gets an Important Changes
entry.

This is stacked on #26283 (merge that first). It also updates the
`nestjs-12` Cloudflare `RUNTIME` branch from #26283: `url.scheme` is now
the shared `'http'`, and `url.port` becomes `{ type: 'integer', value:
3030 }`.

**How to review:** The fix is two lines in
`packages/core/src/utils/url.ts`. The rest updates test expectations in
core (including the outgoing `node:http` path), bun, cloudflare,
`cloudflare-integration-tests`, and the `deno`, `cloudflare-mcp` and
`nestjs-12` e2e apps.

**Unsure about:** Key naming, not changed here: for `kind === 'server'`,
the helper sets `url.port`, while Node server spans set `server.port`
(OTel HTTP server spans use `server.port`). The helper already uses
`server.address` for server spans, so `server.port` may be the better
key there. That rename would change product-visible data, so it needs a
separate decision.

Refs #24844

<!-- junior-request-attribution:start -->
via **Isaac Schlueter**.
<!-- junior-request-attribution:end -->

<!-- junior-session-footer:start -->
<!-- junior-conversation-id:agent%3A6011a8eed2b7dc364fe22ff740bf6e29 -->

--

[View
Session](https://junior-prod.sentry.dev/conversations/agent%3A6011a8eed2b7dc364fe22ff740bf6e29)
[[Sentry]](https://sentry.sentry.io/explore/conversations/agent%3A6011a8eed2b7dc364fe22ff740bf6e29/?project=4510944073809921)

<!-- junior-session-footer:end -->

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-authored-by: Isaac Schlueter <isaac.schlueter@sentry.io>
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