From 1a8c2cd2870b6f612ab4fcc8b52b3f22a59f0655 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Mon, 25 May 2026 11:10:55 +0200 Subject: [PATCH 1/2] test(deno): run optional e2e against latest Deno --- .github/workflows/build.yml | 7 ++++++- .../test-applications/deno-streamed/package.json | 8 ++++++++ .../e2e-tests/test-applications/deno/package.json | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8356c1930c18..8ca0b176b992 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -999,7 +999,7 @@ jobs: if: matrix.test-application == 'deno' || matrix.test-application == 'deno-streamed' uses: denoland/setup-deno@v2.0.4 with: - deno-version: v2.1.5 + deno-version: ${{ matrix.deno-version || 'v2.1.5' }} - name: Restore caches uses: ./.github/actions/restore-cache with: @@ -1118,6 +1118,11 @@ jobs: uses: actions/setup-node@v6 with: node-version-file: 'dev-packages/e2e-tests/test-applications/${{ matrix.test-application }}/package.json' + - name: Set up Deno + if: matrix.test-application == 'deno' || matrix.test-application == 'deno-streamed' + uses: denoland/setup-deno@v2.0.4 + with: + deno-version: ${{ matrix.deno-version || 'v2.1.5' }} - name: Restore caches uses: ./.github/actions/restore-cache with: diff --git a/dev-packages/e2e-tests/test-applications/deno-streamed/package.json b/dev-packages/e2e-tests/test-applications/deno-streamed/package.json index 282f8abb6492..acc417cd3cd0 100644 --- a/dev-packages/e2e-tests/test-applications/deno-streamed/package.json +++ b/dev-packages/e2e-tests/test-applications/deno-streamed/package.json @@ -21,5 +21,13 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "optionalVariants": [ + { + "deno-version": "latest", + "label": "deno-streamed (latest)" + } + ] } } diff --git a/dev-packages/e2e-tests/test-applications/deno/package.json b/dev-packages/e2e-tests/test-applications/deno/package.json index d46cc08530c5..d408ed2816db 100644 --- a/dev-packages/e2e-tests/test-applications/deno/package.json +++ b/dev-packages/e2e-tests/test-applications/deno/package.json @@ -21,5 +21,13 @@ }, "volta": { "extends": "../../package.json" + }, + "sentryTest": { + "optionalVariants": [ + { + "deno-version": "latest", + "label": "deno (latest)" + } + ] } } From 71a9c9f328e71fd440bc7c2c75b94e8d5d0f7739 Mon Sep 17 00:00:00 2001 From: Abdelrahman Awad Date: Mon, 25 May 2026 11:28:17 +0200 Subject: [PATCH 2/2] fix(deno): patch Deno.serve safely --- packages/deno/src/integrations/deno-serve.ts | 48 ++++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/deno/src/integrations/deno-serve.ts b/packages/deno/src/integrations/deno-serve.ts index adb4d39a74d0..3b7dc443371b 100644 --- a/packages/deno/src/integrations/deno-serve.ts +++ b/packages/deno/src/integrations/deno-serve.ts @@ -1,5 +1,5 @@ import type { IntegrationFn } from '@sentry/core'; -import { defineIntegration } from '@sentry/core'; +import { debug, defineIntegration } from '@sentry/core'; import { setAsyncLocalStorageAsyncContextStrategy } from '../async'; import type { RequestHandlerWrapperOptions } from '../wrap-deno-request-handler'; import { wrapDenoRequestHandler } from '../wrap-deno-request-handler'; @@ -44,24 +44,44 @@ const applyHandlerWrap = ( () => handler(request, info as Deno.ServeHandlerInfo), )) as Deno.ServeHandler; +const instrumentedDenoServe = (serve: typeof Deno.serve): typeof Deno.serve => + new Proxy(serve, { + apply(target, thisArg, args: ServeParams) { + if (isSimpleHandler(args)) { + args[0] = applyHandlerWrap(args[0]); + } else if (isServeOptWithFunction(args)) { + args[1] = applyHandlerWrap(args[1], args[0]); + } else if (isServeInitOptions(args)) { + args[0].handler = applyHandlerWrap(args[0].handler, args[0]); + } + // if none of those matched, it'll crash, most likely. + return target.apply(thisArg, args); + }, + }); + const _denoServeIntegration = (() => { return { name: INTEGRATION_NAME, setupOnce() { setAsyncLocalStorageAsyncContextStrategy(); - Deno.serve = new Proxy(Deno.serve, { - apply(target, thisArg, args: ServeParams) { - if (isSimpleHandler(args)) { - args[0] = applyHandlerWrap(args[0]); - } else if (isServeOptWithFunction(args)) { - args[1] = applyHandlerWrap(args[1], args[0]); - } else if (isServeInitOptions(args)) { - args[0].handler = applyHandlerWrap(args[0].handler, args[0]); - } - // if none of those matched, it'll crash, most likely. - return target.apply(thisArg, args); - }, - }); + + const originalServe = Deno.serve; + const wrappedServe = instrumentedDenoServe(originalServe); + + try { + const descriptor = Object.getOwnPropertyDescriptor(Deno, 'serve'); + + Object.defineProperty(Deno, 'serve', { + configurable: descriptor?.configurable ?? true, + enumerable: descriptor?.enumerable ?? true, + // writable: true avoids other instrumentations on older Deno versions + // from crashing if they used to do assignment + writable: true, + value: wrappedServe, + }); + } catch (error) { + debug.warn('Could not instrument Deno.serve.', error); + } }, }; }) satisfies IntegrationFn;