Skip to content

Commit 14306a0

Browse files
authored
Merge pull request #7599 from getsentry/prepare-release/7.45.0
meta: Update CHANGELOG for 7.45.0
2 parents 7f8896a + 210b70f commit 14306a0

File tree

164 files changed

+13493
-462
lines changed

Some content is hidden

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

164 files changed

+13493
-462
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,10 @@ jobs:
321321
uses: ./.github/actions/restore-cache
322322
env:
323323
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}
324-
- name: Run linter
324+
- name: Lint source files
325325
run: yarn lint
326+
- name: Validate ES5 builds
327+
run: yarn validate:es5
326328

327329
job_circular_dep_check:
328330
name: Circular Dependency Check

.github/workflows/flaky-test-detector.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,5 @@ jobs:
7777
working-directory: packages/browser-integration-tests
7878
env:
7979
CHANGED_TEST_PATHS: ${{ steps.changed.outputs.browser_integration_files }}
80-
# Run 100 times when detecting changed test(s), else run all tests 5x
81-
TEST_RUN_COUNT: ${{ steps.changed.outputs.browser_integration == 'true' && 100 || 5 }}
80+
# Run 50 times when detecting changed test(s), else run all tests 5x
81+
TEST_RUN_COUNT: ${{ steps.changed.outputs.browser_integration == 'true' && 50 || 5 }}

.github/workflows/release-size-info.yml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,9 @@ jobs:
1717
name: 'Add size-limit info to release'
1818

1919
steps:
20-
# https://github.com/actions-ecosystem/action-regex-match
21-
- name: Extract version from ref
22-
uses: actions-ecosystem/action-regex-match@v2
23-
id: head_version
24-
with:
25-
# Parse version from head ref, which is refs/tags/<tag_name>
26-
text: ${{ env.GITHUB_REF }}
27-
regex: '^refs\/tags\/([\d.]+)$'
28-
2920
- name: Get version
3021
id: get_version
31-
run: echo "version=${{ github.event.inputs.version || steps.head_version.outputs.group1 }}" >> $GITHUB_OUTPUT
22+
run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name }}" >> $GITHUB_OUTPUT
3223

3324
- name: Update Github Release
3425
if: steps.get_version.outputs.version != ''

CHANGELOG.md

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

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

7+
## 7.45.0
8+
9+
- build(cdn): Ensure ES5 bundles do not use non-ES5 code (#7550)
10+
- feat(core): Add trace function (#7556)
11+
- feat(hub): Make scope always defined on the hub (#7551)
12+
- feat(replay): Add `replay_id` to transaction DSC (#7571)
13+
- feat(replay): Capture fetch body size for replay events (#7524)
14+
- feat(sveltekit): Add performance monitoring for client load (#7537)
15+
- feat(sveltekit): Add performance monitoring for server load (#7536)
16+
- feat(sveltekit): Add performance monitoring to Sveltekit server handle (#7532)
17+
- feat(sveltekit): Add SvelteKit routing instrumentation (#7565)
18+
- fix(browser): Ensure keepalive flag is correctly set for parallel requests (#7553)
19+
- fix(core): Ensure `ignoreErrors` only applies to error events (#7573)
20+
- fix(node): Consider tracing error handler for process exit (#7558)
21+
- fix(otel): Make sure we use correct hub on finish (#7577)
22+
- fix(react): Handle case where error.cause already defined (#7557)
23+
724
## 7.44.2
825

926
- fix(cdn): Fix ES5 CDN bundles (#7544)

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"link:yarn": "lerna exec yarn link",
2424
"lint": "lerna run lint",
2525
"lint:eslint": "lerna run lint:eslint",
26+
"validate:es5": "lerna run validate:es5",
2627
"postpublish": "lerna run --stream --concurrency 1 postpublish",
2728
"test": "lerna run --ignore @sentry-internal/* test",
2829
"test:unit": "lerna run --ignore @sentry-internal/* test:unit",
@@ -89,6 +90,7 @@
8990
"chai": "^4.1.2",
9091
"codecov": "^3.6.5",
9192
"deepmerge": "^4.2.2",
93+
"es-check": "7.1.0",
9294
"eslint": "7.32.0",
9395
"jest": "^27.5.1",
9496
"jest-environment-node": "^27.5.1",

packages/browser-integration-tests/scripts/detectFlakyTests.ts

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,72 @@ import { promisify } from 'util';
66
const exec = promisify(childProcess.exec);
77

88
async function run(): Promise<void> {
9-
let testPaths = getTestPaths();
10-
let failed = [];
9+
let testPaths: string[] = [];
1110

12-
try {
13-
const changedPaths: string[] = process.env.CHANGED_TEST_PATHS ? JSON.parse(process.env.CHANGED_TEST_PATHS) : [];
11+
const changedPaths: string[] = process.env.CHANGED_TEST_PATHS ? JSON.parse(process.env.CHANGED_TEST_PATHS) : [];
1412

15-
if (changedPaths.length > 0) {
16-
console.log(`Detected changed test paths:
13+
if (changedPaths.length > 0) {
14+
console.log(`Detected changed test paths:
1715
${changedPaths.join('\n')}
1816
1917
`);
2018

21-
testPaths = testPaths.filter(p => changedPaths.some(changedPath => changedPath.includes(p)));
19+
testPaths = getTestPaths().filter(p => changedPaths.some(changedPath => changedPath.includes(p)));
20+
if (testPaths.length === 0) {
21+
console.log('Could not find matching tests, aborting...');
22+
process.exit(1);
2223
}
23-
} catch {
24-
console.log('Could not detect changed test paths, running all tests.');
2524
}
2625

2726
const cwd = path.join(__dirname, '../');
2827
const runCount = parseInt(process.env.TEST_RUN_COUNT || '10');
2928

30-
for (const testPath of testPaths) {
31-
console.log(`Running test: ${testPath}`);
32-
const start = Date.now();
29+
try {
30+
await new Promise<void>((resolve, reject) => {
31+
const cp = childProcess.spawn(
32+
`yarn playwright test ${
33+
testPaths.length ? testPaths.join(' ') : './suites'
34+
} --browser='all' --reporter='line' --repeat-each ${runCount}`,
35+
{ shell: true, cwd },
36+
);
37+
38+
let error: Error | undefined;
39+
40+
cp.stdout.on('data', data => {
41+
console.log(data ? (data as object).toString() : '');
42+
});
3343

34-
try {
35-
await exec(`yarn playwright test ${testPath} --browser='all' --repeat-each ${runCount}`, {
36-
cwd,
44+
cp.stderr.on('data', data => {
45+
console.log(data ? (data as object).toString() : '');
3746
});
38-
const end = Date.now();
39-
console.log(` ☑️ Passed ${runCount} times, avg. duration ${Math.ceil((end - start) / runCount)}ms`);
40-
} catch (error) {
41-
logError(error);
42-
failed.push(testPath);
43-
}
44-
}
4547

46-
console.log('');
47-
console.log('');
48+
cp.on('error', e => {
49+
console.error(e);
50+
error = e;
51+
});
4852

49-
if (failed.length > 0) {
50-
console.error(`⚠️ ${failed.length} test(s) failed.`);
53+
cp.on('close', status => {
54+
const err = error || (status !== 0 ? new Error(`Process exited with status ${status}`) : undefined);
55+
56+
if (err) {
57+
reject(err);
58+
} else {
59+
resolve();
60+
}
61+
});
62+
});
63+
} catch (error) {
64+
console.log('');
65+
console.log('');
66+
67+
console.error(`⚠️ Some tests failed.`);
68+
console.error(error);
5169
process.exit(1);
52-
} else {
53-
console.log(`☑️ ${testPaths.length} test(s) passed.`);
5470
}
71+
72+
console.log('');
73+
console.log('');
74+
console.log(`☑️ All tests passed.`);
5575
}
5676

5777
function getTestPaths(): string[] {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as Sentry from '@sentry/browser';
2+
import { Integrations } from '@sentry/tracing';
3+
4+
window.Sentry = Sentry;
5+
window.Replay = new Sentry.Replay({
6+
flushMinDelay: 200,
7+
flushMaxDelay: 200,
8+
useCompression: false,
9+
});
10+
11+
Sentry.init({
12+
dsn: 'https://[email protected]/1337',
13+
integrations: [new Integrations.BrowserTracing({ tracingOrigins: [/.*/] }), window.Replay],
14+
environment: 'production',
15+
tracesSampleRate: 1,
16+
replaysSessionSampleRate: 0.0,
17+
replaysOnErrorSampleRate: 1.0,
18+
});
19+
20+
Sentry.configureScope(scope => {
21+
scope.setUser({ id: 'user123', segment: 'segmentB' });
22+
scope.setTransactionName('testTransactionDSC');
23+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { expect } from '@playwright/test';
2+
import type { EventEnvelopeHeaders } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../utils/fixtures';
5+
import { envelopeHeaderRequestParser, getFirstSentryEnvelopeRequest } from '../../../utils/helpers';
6+
import { getReplaySnapshot, shouldSkipReplayTest, waitForReplayRunning } from '../../../utils/replayHelpers';
7+
8+
sentryTest('should add replay_id to dsc of transactions', async ({ getLocalTestPath, page, browserName }) => {
9+
// This is flaky on webkit, so skipping there...
10+
if (shouldSkipReplayTest() || browserName === 'webkit') {
11+
sentryTest.skip();
12+
}
13+
14+
const url = await getLocalTestPath({ testDir: __dirname });
15+
await page.goto(url);
16+
17+
const envHeader = await getFirstSentryEnvelopeRequest<EventEnvelopeHeaders>(page, url, envelopeHeaderRequestParser);
18+
19+
await waitForReplayRunning(page);
20+
const replay = await getReplaySnapshot(page);
21+
22+
expect(replay.session?.id).toBeDefined();
23+
24+
expect(envHeader.trace).toBeDefined();
25+
expect(envHeader.trace).toEqual({
26+
environment: 'production',
27+
user_segment: 'segmentB',
28+
sample_rate: '1',
29+
trace_id: expect.any(String),
30+
public_key: 'public',
31+
replay_id: replay.session?.id,
32+
});
33+
});

packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/contentLengthHeader/test.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { expect } from '@playwright/test';
22

33
import { sentryTest } from '../../../../../utils/fixtures';
44
import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers';
5-
import { shouldSkipReplayTest } from '../../../../../utils/replayHelpers';
5+
import {
6+
getCustomRecordingEvents,
7+
shouldSkipReplayTest,
8+
waitForReplayRequest,
9+
} from '../../../../../utils/replayHelpers';
610

711
sentryTest('parses response_body_size from Content-Length header if available', async ({ getLocalTestPath, page }) => {
812
if (shouldSkipReplayTest()) {
@@ -22,7 +26,17 @@ sentryTest('parses response_body_size from Content-Length header if available',
2226
});
2327
});
2428

29+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
30+
return route.fulfill({
31+
status: 200,
32+
contentType: 'application/json',
33+
body: JSON.stringify({ id: 'test-id' }),
34+
});
35+
});
36+
2537
const requestPromise = waitForErrorRequest(page);
38+
const replayRequestPromise1 = waitForReplayRequest(page, 0);
39+
2640
const url = await getLocalTestPath({ testDir: __dirname });
2741
await page.goto(url);
2842

@@ -58,4 +72,20 @@ sentryTest('parses response_body_size from Content-Length header if available',
5872
url: 'http://localhost:7654/foo',
5973
},
6074
});
75+
76+
const replayReq1 = await replayRequestPromise1;
77+
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
78+
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
79+
{
80+
data: {
81+
method: 'GET',
82+
responseBodySize: 789,
83+
statusCode: 200,
84+
},
85+
description: 'http://localhost:7654/foo',
86+
endTimestamp: expect.any(Number),
87+
op: 'resource.fetch',
88+
startTimestamp: expect.any(Number),
89+
},
90+
]);
6191
});

packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/noContentLengthHeader/test.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { expect } from '@playwright/test';
22

33
import { sentryTest } from '../../../../../utils/fixtures';
44
import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers';
5-
import { shouldSkipReplayTest } from '../../../../../utils/replayHelpers';
5+
import {
6+
getCustomRecordingEvents,
7+
shouldSkipReplayTest,
8+
waitForReplayRequest,
9+
} from '../../../../../utils/replayHelpers';
610

711
sentryTest('does not capture response_body_size without Content-Length header', async ({ getLocalTestPath, page }) => {
812
if (shouldSkipReplayTest()) {
@@ -22,7 +26,17 @@ sentryTest('does not capture response_body_size without Content-Length header',
2226
});
2327
});
2428

29+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
30+
return route.fulfill({
31+
status: 200,
32+
contentType: 'application/json',
33+
body: JSON.stringify({ id: 'test-id' }),
34+
});
35+
});
36+
2537
const requestPromise = waitForErrorRequest(page);
38+
const replayRequestPromise1 = waitForReplayRequest(page, 0);
39+
2640
const url = await getLocalTestPath({ testDir: __dirname });
2741
await page.goto(url);
2842

@@ -57,4 +71,20 @@ sentryTest('does not capture response_body_size without Content-Length header',
5771
url: 'http://localhost:7654/foo',
5872
},
5973
});
74+
75+
const replayReq1 = await replayRequestPromise1;
76+
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
77+
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
78+
{
79+
data: {
80+
method: 'GET',
81+
responseBodySize: 29,
82+
statusCode: 200,
83+
},
84+
description: 'http://localhost:7654/foo',
85+
endTimestamp: expect.any(Number),
86+
op: 'resource.fetch',
87+
startTimestamp: expect.any(Number),
88+
},
89+
]);
6090
});

packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/nonTextBody/test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { expect } from '@playwright/test';
22

33
import { sentryTest } from '../../../../../utils/fixtures';
44
import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers';
5-
import { shouldSkipReplayTest } from '../../../../../utils/replayHelpers';
5+
import {
6+
getCustomRecordingEvents,
7+
shouldSkipReplayTest,
8+
waitForReplayRequest,
9+
} from '../../../../../utils/replayHelpers';
610

711
sentryTest('calculates body sizes for non-string bodies', async ({ getLocalTestPath, page }) => {
812
if (shouldSkipReplayTest()) {
@@ -19,7 +23,17 @@ sentryTest('calculates body sizes for non-string bodies', async ({ getLocalTestP
1923
});
2024
});
2125

26+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
27+
return route.fulfill({
28+
status: 200,
29+
contentType: 'application/json',
30+
body: JSON.stringify({ id: 'test-id' }),
31+
});
32+
});
33+
2234
const requestPromise = waitForErrorRequest(page);
35+
const replayRequestPromise1 = waitForReplayRequest(page, 0);
36+
2337
const url = await getLocalTestPath({ testDir: __dirname });
2438
await page.goto(url);
2539

@@ -60,4 +74,21 @@ sentryTest('calculates body sizes for non-string bodies', async ({ getLocalTestP
6074
url: 'http://localhost:7654/foo',
6175
},
6276
});
77+
78+
const replayReq1 = await replayRequestPromise1;
79+
const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1);
80+
expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([
81+
{
82+
data: {
83+
method: 'POST',
84+
requestBodySize: 26,
85+
responseBodySize: 24,
86+
statusCode: 200,
87+
},
88+
description: 'http://localhost:7654/foo',
89+
endTimestamp: expect.any(Number),
90+
op: 'resource.fetch',
91+
startTimestamp: expect.any(Number),
92+
},
93+
]);
6394
});

0 commit comments

Comments
 (0)