Skip to content

Commit 676dc4c

Browse files
authored
Merge pull request #7437 from getsentry/prepare-release/7.43.0
meta(changelog): Update changelog for 7.43.0
2 parents 13d725c + 2c25610 commit 676dc4c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1787
-93
lines changed

.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,10 @@
2323
"yaml.schemas": {
2424
"https://json.schemastore.org/github-workflow.json": ".github/workflows/**.yml"
2525
},
26+
"eslint.packageManager": "yarn",
27+
"eslint.workingDirectories": [
28+
{
29+
"mode": "auto"
30+
}
31+
]
2632
}

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.43.0
8+
9+
- feat(nextjs): Run source map upload in Vercel develop and preview environments (#7436)
10+
- feat(types): Add `profilesSampler` option to node client type (#7385)
11+
- fix(core): Avoid using `Array.findIndex()` as it is ES5 incompatible (#7400)
12+
- fix(nextjs): Add better error messages for missing params during next build (#7434)
13+
- fix(nextjs): Don't crash build when auth token is missing
14+
- fix(node): Revert to dynamic `require` call to fix monkey patching (#7430)
15+
- fix(types): Fix node types & add E2E test (#7429)
16+
17+
718
## 7.42.0
819

920
- feat(core): Add lifecycle hooks (#7370)

packages/browser/src/integrations/breadcrumbs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ function _consoleBreadcrumb(handlerData: HandlerData & { args: unknown[]; level:
216216
/**
217217
* Creates breadcrumbs from XHR API calls
218218
*/
219-
function _xhrBreadcrumb(handlerData: HandlerData & { xhr: SentryWrappedXMLHttpRequest }): void {
219+
function _xhrBreadcrumb(handlerData: HandlerData & { xhr: XMLHttpRequest & SentryWrappedXMLHttpRequest }): void {
220220
if (handlerData.endTimestamp) {
221221
// We only capture complete, non-sentry requests
222222
if (handlerData.xhr.__sentry_own_request__) {
@@ -248,7 +248,7 @@ function _xhrBreadcrumb(handlerData: HandlerData & { xhr: SentryWrappedXMLHttpRe
248248
/**
249249
* Creates breadcrumbs from fetch API calls
250250
*/
251-
function _fetchBreadcrumb(handlerData: HandlerData & HandlerDataFetch): void {
251+
function _fetchBreadcrumb(handlerData: HandlerData & HandlerDataFetch & { response?: Response }): void {
252252
// We only capture complete fetch requests
253253
if (!handlerData.endTimestamp) {
254254
return;

packages/core/src/integration.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export function getIntegrationsToSetup(options: Options): Integration[] {
6969
// `beforeSendTransaction`. It therefore has to run after all other integrations, so that the changes of all event
7070
// processors will be reflected in the printed values. For lack of a more elegant way to guarantee that, we therefore
7171
// locate it and, assuming it exists, pop it out of its current spot and shove it onto the end of the array.
72-
const debugIndex = finalIntegrations.findIndex(integration => integration.name === 'Debug');
72+
const debugIndex = findIndex(finalIntegrations, integration => integration.name === 'Debug');
7373
if (debugIndex !== -1) {
7474
const [debugInstance] = finalIntegrations.splice(debugIndex, 1);
7575
finalIntegrations.push(debugInstance);
@@ -107,3 +107,14 @@ export function setupIntegration(integration: Integration, integrationIndex: Int
107107
__DEBUG_BUILD__ && logger.log(`Integration installed: ${integration.name}`);
108108
}
109109
}
110+
111+
// Polyfill for Array.findIndex(), which is not supported in ES5
112+
function findIndex<T>(arr: T[], callback: (item: T) => boolean): number {
113+
for (let i = 0; i < arr.length; i++) {
114+
if (callback(arr[i]) === true) {
115+
return i;
116+
}
117+
}
118+
119+
return -1;
120+
}

packages/e2e-tests/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ current state.
77

88
Prerequisites: Docker
99

10+
- Copy `.env.example` to `.env`
11+
- Fill in auth information in `.env` for an example Sentry project
12+
- The `E2E_TEST_AUTH_TOKEN` must have all the default permissions
13+
1014
```bash
1115
yarn test:e2e
1216
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@sentry:registry=http://localhost:4873
2+
@sentry-internal:registry=http://localhost:4873
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "node-express-app",
3+
"version": "1.0.0",
4+
"private": true,
5+
"scripts": {
6+
"build": "yarn tsc",
7+
"start": "node dist/app.js",
8+
"test": "yarn playwright test"
9+
},
10+
"dependencies": {
11+
"@sentry/integrations": "*",
12+
"@sentry/node": "*",
13+
"@sentry/tracing": "*",
14+
"@sentry/types": "*",
15+
"express": "4.18.2",
16+
"@types/express": "4.17.17",
17+
"@types/node": "18.15.1",
18+
"typescript": "4.9.5"
19+
},
20+
"devDependencies": {
21+
"@playwright/test": "^1.27.1"
22+
}
23+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import type { PlaywrightTestConfig } from '@playwright/test';
2+
import { devices } from '@playwright/test';
3+
4+
/**
5+
* See https://playwright.dev/docs/test-configuration.
6+
*/
7+
const config: PlaywrightTestConfig = {
8+
testDir: './tests',
9+
/* Maximum time one test can run for. */
10+
timeout: 60 * 1000,
11+
expect: {
12+
/**
13+
* Maximum time expect() should wait for the condition to be met.
14+
* For example in `await expect(locator).toHaveText();`
15+
*/
16+
timeout: 5000,
17+
},
18+
/* Run tests in files in parallel */
19+
fullyParallel: true,
20+
/* Fail the build on CI if you accidentally left test.only in the source code. */
21+
forbidOnly: !!process.env.CI,
22+
/* Retry on CI only */
23+
retries: 0,
24+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
25+
reporter: 'list',
26+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
27+
use: {
28+
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
29+
actionTimeout: 0,
30+
/* Base URL to use in actions like `await page.goto('/')`. */
31+
// baseURL: 'http://localhost:3000',
32+
33+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
34+
trace: 'on-first-retry',
35+
},
36+
37+
/* Configure projects for major browsers */
38+
projects: [
39+
{
40+
name: 'chromium',
41+
use: {
42+
...devices['Desktop Chrome'],
43+
},
44+
},
45+
// For now we only test Chrome!
46+
// {
47+
// name: 'firefox',
48+
// use: {
49+
// ...devices['Desktop Firefox'],
50+
// },
51+
// },
52+
// {
53+
// name: 'webkit',
54+
// use: {
55+
// ...devices['Desktop Safari'],
56+
// },
57+
// },
58+
],
59+
60+
/* Run your local dev server before starting the tests */
61+
webServer: {
62+
command: 'yarn start',
63+
port: 3000,
64+
},
65+
};
66+
67+
export default config;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import * as Sentry from '@sentry/node';
2+
import '@sentry/tracing';
3+
import * as Integrations from '@sentry/integrations';
4+
import express from 'express';
5+
6+
declare global {
7+
namespace globalThis {
8+
var transactionIds: string[];
9+
}
10+
}
11+
12+
Sentry.init({
13+
dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN,
14+
integrations: [new Integrations.HttpClient()],
15+
debug: true,
16+
tracesSampleRate: 1,
17+
});
18+
19+
const app = express();
20+
const port = 3000;
21+
22+
app.use(Sentry.Handlers.requestHandler());
23+
app.use(Sentry.Handlers.tracingHandler());
24+
25+
app.get('/test-success', function (req, res) {
26+
res.send({ version: 'v1' });
27+
});
28+
29+
app.get('/test-param/:param', function (req, res) {
30+
res.send({ paramWas: req.params.param });
31+
});
32+
33+
app.get('/test-transaction', async function (req, res) {
34+
const transaction = Sentry.startTransaction({ name: 'test-transaction', op: 'e2e-test' });
35+
Sentry.getCurrentHub().configureScope(scope => scope.setSpan(transaction));
36+
37+
const span = transaction.startChild();
38+
39+
span.finish();
40+
transaction.finish();
41+
42+
await Sentry.flush();
43+
44+
res.send({
45+
transactionIds: global.transactionIds || [],
46+
});
47+
});
48+
49+
app.get('/test-error', async function (req, res) {
50+
const exceptionId = Sentry.captureException(new Error('This is an error'));
51+
52+
await Sentry.flush(2000);
53+
54+
res.send({ exceptionId });
55+
});
56+
57+
app.listen(port, () => {
58+
console.log(`Example app listening on port ${port}`);
59+
});
60+
61+
Sentry.addGlobalEventProcessor(event => {
62+
global.transactionIds = global.transactionIds || [];
63+
64+
if (event.type === 'transaction') {
65+
const eventId = event.event_id;
66+
67+
if (eventId) {
68+
global.transactionIds.push(eventId);
69+
}
70+
}
71+
72+
return event;
73+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"$schema": "../../test-recipe-schema.json",
3+
"testApplicationName": "Node Express App",
4+
"buildCommand": "yarn install && yarn build",
5+
"tests": [
6+
{
7+
"testName": "Test express server",
8+
"testCommand": "yarn test",
9+
"timeoutSeconds": 60
10+
}
11+
]
12+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { test, expect } from '@playwright/test';
2+
import axios, { AxiosError } from 'axios';
3+
4+
const authToken = process.env.E2E_TEST_AUTH_TOKEN;
5+
const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG;
6+
const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT;
7+
const EVENT_POLLING_TIMEOUT = 30_000;
8+
9+
test('Sends exception to Sentry', async ({ baseURL }) => {
10+
const { data } = await axios.get(`${baseURL}/test-error`);
11+
const { exceptionId } = data;
12+
13+
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionId}/`;
14+
15+
console.log(`Polling for error eventId: ${exceptionId}`);
16+
17+
await expect
18+
.poll(
19+
async () => {
20+
try {
21+
const response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });
22+
23+
return response.status;
24+
} catch (e) {
25+
if (e instanceof AxiosError && e.response) {
26+
if (e.response.status !== 404) {
27+
throw e;
28+
} else {
29+
return e.response.status;
30+
}
31+
} else {
32+
throw e;
33+
}
34+
}
35+
},
36+
{ timeout: EVENT_POLLING_TIMEOUT },
37+
)
38+
.toBe(200);
39+
});
40+
41+
test('Sends transactions to Sentry', async ({ baseURL }) => {
42+
const { data } = await axios.get(`${baseURL}/test-transaction`);
43+
const { transactionIds } = data;
44+
45+
console.log(`Polling for transaction eventIds: ${JSON.stringify(transactionIds)}`);
46+
47+
expect(transactionIds.length).toBeGreaterThan(0);
48+
49+
await Promise.all(
50+
transactionIds.map(async (transactionId: string) => {
51+
const url = `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionId}/`;
52+
53+
await expect
54+
.poll(
55+
async () => {
56+
try {
57+
const response = await axios.get(url, { headers: { Authorization: `Bearer ${authToken}` } });
58+
59+
return response.status;
60+
} catch (e) {
61+
if (e instanceof AxiosError && e.response) {
62+
if (e.response.status !== 404) {
63+
throw e;
64+
} else {
65+
return e.response.status;
66+
}
67+
} else {
68+
throw e;
69+
}
70+
}
71+
},
72+
{ timeout: EVENT_POLLING_TIMEOUT },
73+
)
74+
.toBe(200);
75+
}),
76+
);
77+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"types": ["node"],
4+
"esModuleInterop": true,
5+
"lib": ["ES6"],
6+
"strict": true,
7+
"outDir": "dist"
8+
},
9+
"include": ["src/**/*.ts"]
10+
}

0 commit comments

Comments
 (0)