Skip to content

Commit 7334e14

Browse files
authored
Merge branch 'develop' into cg/js-2209-event-processor-migration-nextjs-edge-event-processors
2 parents 04e5262 + f72f743 commit 7334e14

52 files changed

Lines changed: 1577 additions & 515 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: 'Nx Affected List'
2+
description: 'Outputs a space-separated list of Nx projects affected by changes between base and head commits.'
3+
4+
inputs:
5+
base:
6+
description: 'Base commit SHA'
7+
required: false
8+
head:
9+
description: 'Head commit SHA'
10+
required: false
11+
12+
outputs:
13+
affected:
14+
description: 'Space-separated list of affected project names'
15+
value: ${{ steps.affected.outputs.affected }}
16+
17+
runs:
18+
using: 'composite'
19+
steps:
20+
- name: Get affected Nx projects
21+
id: affected
22+
shell: bash
23+
env:
24+
INPUT_BASE: ${{ inputs.base }}
25+
INPUT_HEAD: ${{ inputs.head }}
26+
run: |
27+
set -euo pipefail
28+
extra_args=()
29+
if [ -n "${INPUT_BASE:-}" ]; then extra_args+=(--base="$INPUT_BASE"); fi
30+
if [ -n "${INPUT_HEAD:-}" ]; then extra_args+=(--head="$INPUT_HEAD"); fi
31+
32+
# Fail the step on nx/git errors so empty output cannot skip integration jobs silently.
33+
AFFECTED=$(./node_modules/.bin/nx show projects --affected "${extra_args[@]}" | tr '\n' ' ' | xargs)
34+
echo "affected=$AFFECTED" >> "$GITHUB_OUTPUT"
35+
36+
if [ -n "$AFFECTED" ]; then
37+
echo "Affected projects: $AFFECTED"
38+
else
39+
echo "No affected projects found"
40+
fi

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ jobs:
100100
id: install_dependencies
101101

102102
- name: Check for Affected Nx Projects
103-
uses: dkhunt27/action-nx-affected-list@v6.1
103+
uses: ./.github/actions/nx-affected-list
104104
id: checkForAffected
105105
if: github.event_name == 'pull_request'
106106
with:

.size-limit.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ module.exports = [
9696
path: 'packages/browser/build/npm/esm/prod/index.js',
9797
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'replayCanvasIntegration'),
9898
gzip: true,
99-
limit: '88 KB',
99+
limit: '89 KB',
100100
disablePlugins: ['@size-limit/esbuild'],
101101
},
102102
{
@@ -180,7 +180,7 @@ module.exports = [
180180
path: 'packages/vue/build/esm/index.js',
181181
import: createImport('init'),
182182
gzip: true,
183-
limit: '31 KB',
183+
limit: '32 KB',
184184
disablePlugins: ['@size-limit/esbuild'],
185185
},
186186
{
@@ -212,7 +212,7 @@ module.exports = [
212212
name: 'CDN Bundle (incl. Tracing)',
213213
path: createCDNPath('bundle.tracing.min.js'),
214214
gzip: true,
215-
limit: '46.5 KB',
215+
limit: '47 KB',
216216
disablePlugins: ['@size-limit/esbuild'],
217217
},
218218
{
@@ -226,7 +226,7 @@ module.exports = [
226226
name: 'CDN Bundle (incl. Tracing, Logs, Metrics)',
227227
path: createCDNPath('bundle.tracing.logs.metrics.min.js'),
228228
gzip: true,
229-
limit: '47.5 KB',
229+
limit: '48 KB',
230230
disablePlugins: ['@size-limit/esbuild'],
231231
},
232232
{
@@ -240,14 +240,14 @@ module.exports = [
240240
name: 'CDN Bundle (incl. Tracing, Replay)',
241241
path: createCDNPath('bundle.tracing.replay.min.js'),
242242
gzip: true,
243-
limit: '83.5 KB',
243+
limit: '84 KB',
244244
disablePlugins: ['@size-limit/esbuild'],
245245
},
246246
{
247247
name: 'CDN Bundle (incl. Tracing, Replay, Logs, Metrics)',
248248
path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'),
249249
gzip: true,
250-
limit: '84.5 KB',
250+
limit: '85 KB',
251251
disablePlugins: ['@size-limit/esbuild'],
252252
},
253253
{
@@ -278,7 +278,7 @@ module.exports = [
278278
path: createCDNPath('bundle.tracing.min.js'),
279279
gzip: false,
280280
brotli: false,
281-
limit: '139 KB',
281+
limit: '140 KB',
282282
disablePlugins: ['@size-limit/esbuild'],
283283
},
284284
{
@@ -294,7 +294,7 @@ module.exports = [
294294
path: createCDNPath('bundle.tracing.logs.metrics.min.js'),
295295
gzip: false,
296296
brotli: false,
297-
limit: '142 KB',
297+
limit: '144 KB',
298298
disablePlugins: ['@size-limit/esbuild'],
299299
},
300300
{
@@ -310,15 +310,15 @@ module.exports = [
310310
path: createCDNPath('bundle.tracing.replay.min.js'),
311311
gzip: false,
312312
brotli: false,
313-
limit: '256 KB',
313+
limit: '258 KB',
314314
disablePlugins: ['@size-limit/esbuild'],
315315
},
316316
{
317317
name: 'CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed',
318318
path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'),
319319
gzip: false,
320320
brotli: false,
321-
limit: '260 KB',
321+
limit: '261 KB',
322322
disablePlugins: ['@size-limit/esbuild'],
323323
},
324324
{

dev-packages/e2e-tests/test-applications/hono-4/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"private": true,
66
"scripts": {
77
"dev:cf": "wrangler dev --var \"E2E_TEST_DSN:$E2E_TEST_DSN\" --log-level=$(test $CI && echo 'none' || echo 'log')",
8-
"dev:node": "node --import tsx/esm --import @sentry/node/preload src/entry.node.ts",
8+
"dev:node": "node --import tsx/esm --import ./src/instrument.node.ts src/entry.node.ts",
99
"dev:bun": "bun src/entry.bun.ts",
1010
"build": "wrangler deploy --dry-run",
1111
"test:build": "pnpm install && pnpm build",

dev-packages/e2e-tests/test-applications/hono-4/src/entry.node.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,9 @@ import { sentry } from '@sentry/hono/node';
33
import { serve } from '@hono/node-server';
44
import { addRoutes } from './routes';
55

6-
const app = new Hono<{ Bindings: { E2E_TEST_DSN: string } }>();
6+
const app = new Hono();
77

8-
app.use(
9-
// @ts-expect-error - Env is not yet in type
10-
sentry(app, {
11-
dsn: process.env.E2E_TEST_DSN,
12-
environment: 'qa',
13-
tracesSampleRate: 1.0,
14-
tunnel: 'http://localhost:3031/',
15-
}),
16-
);
8+
app.use(sentry(app));
179

1810
addRoutes(app);
1911

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as Sentry from '@sentry/hono/node';
2+
3+
Sentry.init({
4+
dsn: process.env.E2E_TEST_DSN,
5+
environment: 'qa',
6+
tracesSampleRate: 1.0,
7+
tunnel: 'http://localhost:3031/',
8+
});
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
export type Runtime = 'cloudflare' | 'node' | 'bun';
22

33
export const RUNTIME = (process.env.RUNTIME || 'cloudflare') as Runtime;
4-
export const isNode = RUNTIME === 'node';
54

65
export const APP_NAME = 'hono-4';

dev-packages/e2e-tests/test-applications/hono-4/tests/middleware.test.ts

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,20 @@
11
import { expect, test } from '@playwright/test';
22
import { waitForError, waitForTransaction } from '@sentry-internal/test-utils';
33
import { type SpanJSON } from '@sentry/core';
4-
import { APP_NAME, isNode } from './constants';
5-
6-
// In Node, @sentry/node/preload eagerly activates the OTel HonoInstrumentation,
7-
// which wraps all Hono instance methods at construction time via WrappedHono.
8-
const MIDDLEWARE_ORIGIN = 'auto.middleware.hono';
9-
const OTEL_ORIGIN = 'auto.http.otel.hono';
4+
import { APP_NAME } from './constants';
105

116
const SCENARIOS = [
127
{
138
name: 'root app middleware',
149
prefix: '/test-middleware',
15-
origin: MIDDLEWARE_ORIGIN,
1610
},
1711
{
1812
name: 'sub-app middleware (route group)',
1913
prefix: '/test-subapp-middleware',
20-
origin: isNode ? OTEL_ORIGIN : MIDDLEWARE_ORIGIN,
2114
},
2215
] as const;
2316

24-
for (const { name, prefix, origin } of SCENARIOS) {
17+
for (const { name, prefix } of SCENARIOS) {
2518
test.describe(name, () => {
2619
test('creates a span for named middleware', async ({ baseURL }) => {
2720
const transactionPromise = waitForTransaction(APP_NAME, event => {
@@ -43,7 +36,7 @@ for (const { name, prefix, origin } of SCENARIOS) {
4336
expect.objectContaining({
4437
description: 'middlewareA',
4538
op: 'middleware.hono',
46-
origin,
39+
origin: 'auto.middleware.hono',
4740
status: 'ok',
4841
}),
4942
);
@@ -68,18 +61,13 @@ for (const { name, prefix, origin } of SCENARIOS) {
6861
expect.objectContaining({
6962
description: '<anonymous>',
7063
op: 'middleware.hono',
71-
origin: MIDDLEWARE_ORIGIN,
64+
origin: 'auto.middleware.hono',
7265
status: 'ok',
7366
}),
7467
);
7568
});
7669

7770
test('multiple middleware are sibling spans under the same parent', async ({ baseURL }) => {
78-
test.skip(
79-
isNode,
80-
'Node double-instruments middleware (too many spans) - TODO: fix this in the SDK and re-enable the test',
81-
);
82-
8371
const transactionPromise = waitForTransaction(APP_NAME, event => {
8472
return event.contexts?.trace?.op === 'http.server' && event.transaction === `GET ${prefix}/multi`;
8573
});
@@ -90,7 +78,6 @@ for (const { name, prefix, origin } of SCENARIOS) {
9078
const transaction = await transactionPromise;
9179
const spans = transaction.spans || [];
9280

93-
// Sort spans because they are in a different order in Node/Bun (OTel-based)
9481
const middlewareSpans = spans.sort((a, b) => (a.start_timestamp ?? 0) - (b.start_timestamp ?? 0));
9582

9683
expect(middlewareSpans).toHaveLength(2);
@@ -139,10 +126,6 @@ for (const { name, prefix, origin } of SCENARIOS) {
139126
const transaction = await transactionPromise;
140127
const spans = transaction.spans || [];
141128

142-
// On the /error path only one middleware (failingMiddleware) is registered,
143-
// so we can find the error span by status alone. On Node for sub-apps, the
144-
// OTel layer wraps before patchRoute, so the function name may be lost in
145-
// the patchRoute span — but the error status is always set.
146129
const failingSpan = spans.find(
147130
(span: SpanJSON) => span.op === 'middleware.hono' && span.status === 'internal_error',
148131
);
@@ -169,36 +152,8 @@ for (const { name, prefix, origin } of SCENARIOS) {
169152
});
170153
}
171154

172-
test.describe('.all() handler on sub-app (method ALL edge case)', () => {
173-
test('Node: OTel wraps .all() and produces a hono span', async ({ baseURL }) => {
174-
test.skip(!isNode, 'Node-specific: OTel wraps .all() at construction time');
175-
176-
const transactionPromise = waitForTransaction(APP_NAME, event => {
177-
return (
178-
event.contexts?.trace?.op === 'http.server' && event.transaction === 'GET /test-subapp-middleware/all-handler'
179-
);
180-
});
181-
182-
const response = await fetch(`${baseURL}/test-subapp-middleware/all-handler`);
183-
expect(response.status).toBe(200);
184-
185-
const body = await response.json();
186-
expect(body).toEqual({ handler: 'all' });
187-
188-
const transaction = await transactionPromise;
189-
const spans = transaction.spans || [];
190-
191-
// On Node, OTel wraps .all() at construction time. Since the handler
192-
// returns a Response, OTel classifies it as 'request_handler' (not
193-
// middleware). patchRoute also wraps it but sees the anonymous OTel wrapper.
194-
// Either way, the handler IS instrumented — verify any hono span exists.
195-
const honoSpan = spans.find((span: SpanJSON) => span.op?.endsWith('.hono'));
196-
expect(honoSpan).toBeDefined();
197-
});
198-
199-
test('Bun/Cloudflare: patchRoute wraps .all() as middleware span', async ({ baseURL }) => {
200-
test.skip(isNode, 'Bun/Cloudflare-specific: patchRoute is the sole wrapper');
201-
155+
test.describe('patchRoute wraps .all() as middleware span (in sub-app)', () => {
156+
test('patchRoute wraps .all() as middleware span', async ({ baseURL }) => {
202157
const transactionPromise = waitForTransaction(APP_NAME, event => {
203158
return (
204159
event.contexts?.trace?.op === 'http.server' && event.transaction === 'GET /test-subapp-middleware/all-handler'
@@ -225,7 +180,7 @@ test.describe('.all() handler on sub-app (method ALL edge case)', () => {
225180
expect.objectContaining({
226181
description: 'allCatchAll',
227182
op: 'middleware.hono',
228-
origin: MIDDLEWARE_ORIGIN,
183+
origin: 'auto.middleware.hono',
229184
status: 'ok',
230185
}),
231186
);

dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"@types/react": "^19",
4040
"@types/react-dom": "^19",
4141
"eslint": "^9",
42-
"eslint-config-next": "canary",
42+
"eslint-config-next": "^16",
4343
"typescript": "^5"
4444
},
4545
"volta": {

dev-packages/e2e-tests/test-applications/nextjs-16-cf-workers/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"@types/react": "^19",
3232
"@types/react-dom": "^19",
3333
"eslint": "^9",
34-
"eslint-config-next": "canary",
34+
"eslint-config-next": "^16",
3535
"typescript": "^5",
3636
"wrangler": "^4.61.0"
3737
},
@@ -43,7 +43,9 @@
4343
{
4444
"build-command": "pnpm test:build-latest",
4545
"label": "nextjs-16-cf-workers (latest)"
46-
},
46+
}
47+
],
48+
"optionalVariants": [
4749
{
4850
"build-command": "pnpm test:build-canary",
4951
"label": "nextjs-16-cf-workers (canary)"

0 commit comments

Comments
 (0)