8000 Merge pull request #9771 from getsentry/prepare-release/7.86.0 · adam187/sentry-javascript@ad82dad · GitHub
[go: up one dir, main page]

Skip to content

Commit ad82dad

Browse files
authored
Merge pull request getsentry#9771 from getsentry/prepare-release/7.86.0
meta(changelog): Update changelog for 7.86.0
2 parents 829a15c + 1132994 commit ad82dad

File tree

35 files changed

+471
-135
lines changed

35 files changed

+471
-135
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -976,8 +976,7 @@ jobs:
976976
runs-on: ubuntu-20.04
977977
timeout-minutes: 30
978978
if: |
979-
contains(github.event.pull_request.labels.*.name, 'ci-overhead-measurements') ||
980-
needs.job_get_metadata.outputs.is_develop == 'true'
979+
contains(github.event.pull_request.labels.*.name, 'ci-overhead-measurements')
981980
steps:
982981
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
983982
uses: actions/checkout@v4

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44

55
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
66

7+
## 7.86.0
8+
9+
- feat(core): Use SDK_VERSION for hub API version (#9732)
10+
- feat(nextjs): Emit warning if your app directory doesn't have a global-error.js file (#9753)
11+
- feat(node): Add cloudflare pages commit sha (#9751)
12+
- feat(remix): Bump @sentry/cli to 2.22.3 (#9741)
13+
- fix(nextjs): Don't accidentally trigger static generation bailout (#9749)
14+
- fix(node): Guard `process.env.NODE_ENV` access in Spotlight integration (#9748)
15+
- fix(utils): Fix XHR instrumentation early return (#9770)
16+
- ref(remix): Rework Error Handling (#9725)
17+
718
## 7.85.0
819

920
- feat(core): Add `addEventProcessor` method (#9554)

docs/using-yalc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ to add the local SDK package to your project.
4343

4444
### My changes are not applied to the test project
4545

46-
Did you run `yarn build && yarn publish:yalc` after making your changes?
46+
Did you run `yarn build && yarn yalc:publish` after making your changes?
4747

4848
### My test project uses Vite and I still don't see changes
4949

packages/astro/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414

1515
- [Official SDK Docs](https://docs.sentry.io/platforms/javascript/guides/astro/)
1616

17-
## Experimental Note
17+
## SDK Status
1818

19-
This SDK is experimental and in Alpha state. Breaking changes can occurr at any time.
19+
This SDK is in Beta and not yet fully stable.
2020
If you have feedback or encounter any bugs, feel free to [open an issue](https://github.com/getsentry/sentry-javascript/issues/new/choose).
2121

2222
## General
@@ -58,9 +58,9 @@ SENTRY_AUTH_TOKEN="your-token"
5858

5959
### Server Instrumentation
6060

61-
For Astro apps configured for (hybrid) Server Side Rendering (SSR), the Sentry integration will automatically add middleware to your server to instrument incoming requests **if you're using Astro 3.5.0 or newer**.
61+
For Astro apps configured for (hybrid) Server Side Rendering (SSR), the Sentry integration will automatically add middleware to your server to instrument incoming requests **if you're using Astro 3.5.2 or newer**.
6262

63-
If you're using Astro <3.5.0, complete the setup by adding the Sentry middleware to your `src/middleware.js` file:
63+
If you're using Astro <3.5.2, complete the setup by adding the Sentry middleware to your `src/middleware.js` file:
6464

6565
```javascript
6666
// src/middleware.js

packages/core/src/hub.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { DEFAULT_ENVIRONMENT } from './constants';
2626
import { DEBUG_BUILD } from './debug-build';
2727
import { Scope } from './scope';
2828
import { closeSession, makeSession, updateSession } from './session';
29+
import { SDK_VERSION } from './version';
2930

3031
/**
3132
* API compatibility version of this hub.
@@ -35,7 +36,7 @@ import { closeSession, makeSession, updateSession } from './session';
3536
*
3637
* @hidden
3738
*/
38-
export const API_VERSION = 4;
39+
export const API_VERSION = parseFloat(SDK_VERSION);
3940

4041
/**
4142
* Default maximum number of breadcrumbs added to an event. Can be overwritten

packages/e2e-tests/test-applications/create-remix-app-v2/app/entry.server.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ Sentry.init({
2424
tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
2525
});
2626

27-
export function handleError(error: unknown, { request }: DataFunctionArgs): void {
28-
Sentry.captureRemixServerException(error, 'remix.server', request);
29-
}
27+
export const handleError = Sentry.wrapRemixHandleError;
3028

3129
export default function handleRequest(
3230
request: Request,

packages/e2e-tests/test-applications/create-remix-app/app/entry.server.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ Sentry.init({
2121
tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
2222
});
2323

24-
export function handleError(error: unknown, { request }: DataFunctionArgs): void {
25-
Sentry.captureRemixServerException(error, 'remix.server', request);
26-
}
24+
export const handleError = Sentry.wrapRemixHandleError;
2725

2826
export default function handleRequest(
2927
request: Request,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { NextResponse } from 'next/server';
2+
3+
export async function GET() {
4+
return NextResponse.json({ result: 'static response' });
5+
}
6+
7+
// This export makes it so that this route is always dynamically rendered (i.e Sentry will trace)
8+
export const revalidate = 0;
9+
10+
// This export makes it so that this route will throw an error if the Request object is accessed in some way.
11+
export const dynamic = 'error';

packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,10 @@ test.describe('Edge runtime', () => {
9494
expect(routehandlerError.contexts?.runtime?.name).toBe('vercel-edge');
9595
});
9696
});
97+
98+
test('should not crash route handlers that are configured with `export const dynamic = "error"`', async ({
99+
request,
100+
}) => {
101+
const response = await request.get('/route-handlers/static');
102+
expect(await response.json()).toStrictEqual({ result: 'static response' });
103+
});

packages/nextjs/src/common/types.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,19 @@ export type ServerComponentContext = {
1818
};
1919

2020
export interface RouteHandlerContext {
21-
// TODO(v8): Remove
22-
/**
23-
* @deprecated The SDK will automatically pick up the method from the incoming Request object instead.
24-
*/
2521
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
2622
parameterizedRoute: string;
2723
// TODO(v8): Remove
2824
/**
29-
* @deprecated The SDK will automatically pick up the `sentry-trace` header from the incoming Request object instead.
25+
* @deprecated pass a complete `Headers` object with the `headers` field instead.
3026
*/
3127
sentryTraceHeader?: string;
3228
// TODO(v8): Remove
3329
/**
34-
* @deprecated The SDK will automatically pick up the `baggage` header from the incoming Request object instead.
30+
* @deprecated pass a complete `Headers` object with the `headers` field instead.
3531
*/
3632
baggageHeader?: string;
33+
headers?: WebFetchHeaders;
3734
}
3835

3936
export type VercelCronsConfig = { path?: string; schedule?: string }[] | undefined;

packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { addTracingExtensions, captureException, flush, getCurrentHub, runWithAsyncContext, trace } from '@sentry/core';
2-
import { tracingContextFromHeaders, winterCGRequestToRequestData } from '@sentry/utils';
2+
import { tracingContextFromHeaders, winterCGHeadersToDict } from '@sentry/utils';
33

44
import { isRedirectNavigationError } from './nextNavigationErrorUtils';
55
import type { RouteHandlerContext } from './types';
@@ -15,23 +15,16 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
1515
): (...args: Parameters<F>) => ReturnType<F> extends Promise<unknown> ? ReturnType<F> : Promise<ReturnType<F>> {
1616
addTracingExtensions();
1717
// eslint-disable-next-line deprecation/deprecation
18-
const { method, parameterizedRoute, baggageHeader, sentryTraceHeader } = context;
18+
const { method, parameterizedRoute, baggageHeader, sentryTraceHeader, headers } = context;
1919
return new Proxy(routeHandler, {
2020
apply: (originalFunction, thisArg, args) => {
2121
return runWithAsyncContext(async () => {
2222
const hub = getCurrentHub();
2323
const currentScope = hub.getScope();
2424

25-
let req: Request | undefined;
26-
let reqMethod: string | undefined;
27-
if (args[0] instanceof Request) {
28-
req = args[0];
29-
reqMethod = req.method;
30-
}
31-
3225
const { traceparentData, dynamicSamplingContext, propagationContext } = tracingContextFromHeaders(
33-
sentryTraceHeader,
34-
baggageHeader,
26+
sentryTraceHeader ?? headers?.get('sentry-trace') ?? undefined,
27+
baggageHeader ?? headers?.get('baggage'),
3528
);
3629
currentScope.setPropagationContext(propagationContext);
3730

@@ -40,11 +33,13 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
4033
res = await trace(
4134
{
4235
op: 'http.server',
43-
name: `${reqMethod ?? method} ${parameterizedRoute}`,
36+
name: `${method} ${parameterizedRoute}`,
4437
status: 'ok',
4538
...traceparentData,
4639
metadata: {
47-
request: req ? winterCGRequestToRequestData(req) : undefined,
40+
request: {
41+
headers: headers ? winterCGHeadersToDict(headers) : undefined,
42+
},
4843
source: 'route',
4944
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
5045
},

packages/nextjs/src/config/templates/routeHandlerWrapperTemplate.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as Sentry from '@sentry/nextjs';
2+
import type { WebFetchHeaders } from '@sentry/types';
23
// @ts-expect-error Because we cannot be sure if the RequestAsyncStorage module exists (it is not part of the Next.js public
34
// API) we use a shim if it doesn't exist. The logic for this is in the wrapping loader.
45
import { requestAsyncStorage } from '__SENTRY_NEXTJS_REQUEST_ASYNC_STORAGE_SHIM__';
@@ -34,12 +35,14 @@ function wrapHandler<T>(handler: T, method: 'GET' | 'POST' | 'PUT' | 'PATCH' | '
3435
apply: (originalFunction, thisArg, args) => {
3536
let sentryTraceHeader: string | undefined | null = undefined;
3637
let baggageHeader: string | undefined | null = undefined;
38+
let headers: WebFetchHeaders | undefined = undefined;
3739

3840
// We try-catch here just in case the API around `requestAsyncStorage` changes unexpectedly since it is not public API
3941
try {
4042
const requestAsyncStore = requestAsyncStorage.getStore();
4143
sentryTraceHeader = requestAsyncStore?.headers.get('sentry-trace') ?? undefined;
4244
baggageHeader = requestAsyncStore?.headers.get('baggage') ?? undefined;
45+
headers = requestAsyncStore?.headers;
4346
} catch (e) {
4447
/** empty */
4548
}
@@ -50,6 +53,7 @@ function wrapHandler<T>(handler: T, method: 'GET' | 'POST' | 'PUT' | 'PATCH' | '
5053
parameterizedRoute: '__ROUTE__',
5154
sentryTraceHeader,
5255
baggageHeader,
56+
headers,
5357
}).apply(thisArg, args);
5458
},
5559
});

packages/nextjs/src/config/webpack.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ let showedMissingOrgSlugErrorMsg = false;
4040
let showedMissingProjectSlugErrorMsg = false;
4141
let showedHiddenSourceMapsWarningMsg = false;
4242
let showedMissingCliBinaryWarningMsg = false;
43+
let showedMissingGlobalErrorWarningMsg = false;
4344

4445
// TODO: merge default SentryWebpackPlugin ignore with their SentryWebpackPlugin ignore or ignoreFile
4546
// TODO: merge default SentryWebpackPlugin include with their SentryWebpackPlugin include
@@ -328,6 +329,24 @@ export function constructWebpackConfigFunction(
328329
});
329330
}
330331

332+
if (appDirPath) {
333+
const hasGlobalErrorFile = ['global-error.js', 'global-error.jsx', 'global-error.ts', 'global-error.tsx'].some(
334+
globalErrorFile => fs.existsSync(path.join(appDirPath!, globalErrorFile)),
335+
);
336+
337+
if (!hasGlobalErrorFile && !showedMissingGlobalErrorWarningMsg) {
338+
// eslint-disable-next-line no-console
339+
console.log(
340+
`${chalk.yellow(
341+
'warn',
342+
)} - It seems like you don't have a global error handler set up. It is recommended that you add a ${chalk.cyan(
343+
'global-error.js',
344+
)} file with Sentry instrumentation so that React rendering errors are reported to Sentry. Read more: https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#react-render-errors-in-app-router`,
345+
);
346+
showedMissingGlobalErrorWarningMsg = true;
347+
}
348+
}
349+
331350
// The SDK uses syntax (ES6 and ES6+ features like object spread) which isn't supported by older browsers. For users
332351
// who want to support such browsers, `transpileClientSDK` allows them to force the SDK code to go through the same
333352
// transpilation that their code goes through. We don't turn this on by default because it increases bundle size

packages/node/src/integrations/spotlight.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ export class Spotlight implements Integration {
4141
* Sets up forwarding envelopes to the Spotlight Sidecar
4242
*/
4343
public setup(client: Client): void {
44-
if (process.env.NODE_ENV !== 'development') {
45-
logger.warn("[Spotlight] It seems you're not in dev mode. Do you really want to have Spoltight enabled?");
44+
if (typeof process === 'object' && process.env && process.env.NODE_ENV !== 'development') {
45+
logger.warn("[Spotlight] It seems you're not in dev mode. Do you really want to have Spotlight enabled?");
4646
}
4747
connectToSpotlight(client, this._options);
4848
}

packages/node/src/sdk.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ export function getSentryRelease(fallback?: string): string | undefined {
235235
process.env.ZEIT_GITHUB_COMMIT_SHA ||
236236
process.env.ZEIT_GITLAB_COMMIT_SHA ||
237237
process.env.ZEIT_BITBUCKET_COMMIT_SHA ||
238+
// Cloudflare Pages - https://developers.cloudflare.com/pages/platform/build-configuration/#environment-variables
239+
process.env.CF_PAGES_COMMIT_SHA ||
238240
fallback
239241
);
240242
}

packages/node/test/integrations/spotlight.test.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ describe('Spotlight', () => {
138138
integration.setup(client);
139139

140140
expect(loggerSpy).toHaveBeenCalledWith(
141-
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spoltight enabled?"),
141+
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
142142
);
143143

144144
process.env.NODE_ENV = oldEnvValue;
@@ -152,9 +152,41 @@ describe('Spotlight', () => {
152152
integration.setup(client);
153153

154154
expect(loggerSpy).not.toHaveBeenCalledWith(
155-
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spoltight enabled?"),
155+
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
156156
);
157157

158158
process.env.NODE_ENV = oldEnvValue;
159159
});
160+
161+
it('handles `process` not being available', () => {
162+
const originalProcess = process;
163+
164+
// @ts-expect-error - TS complains but we explicitly wanna test this
165+
delete global.process;
166+
167+
const integration = new Spotlight({ sidecarUrl: 'http://localhost:8969' });
168+
integration.setup(client);
169+
170+
expect(loggerSpy).not.toHaveBeenCalledWith(
171+
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
172+
);
173+
174+
global.process = originalProcess;
175+
});
176+
177+
it('handles `process.env` not being available', () => {
178+
const originalEnv = process.env;
179+
180+
// @ts-expect-error - TS complains but we explicitly wanna test this
181+
delete process.env;
182+
183+
const integration = new Spotlight({ sidecarUrl: 'http://localhost:8969' });
184+
integration.setup(client);
185+
186+
expect(loggerSpy).not.toHaveBeenCalledWith(
187+
expect.stringContaining("It seems you're not in dev mode. Do you really want to have Spotlight enabled?"),
188+
);
189+
190+
process.env = originalEnv;
191+
});
160192
});

packages/remix/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"access": "public"
2828
},
2929
"dependencies": {
30-
"@sentry/cli": "^2.21.2",
30+
"@sentry/cli": "^2.22.3",
3131
"@sentry/core": "7.85.0",
3232
"@sentry/node": "7.85.0",
3333
"@sentry/react": "7.85.0",

0 commit comments

Comments
 (0)
0