Skip to content

Commit 503a1c2

Browse files
authored
Merge pull request #7036 from getsentry/develop
2 parents 980054d + 5e05e04 commit 503a1c2

23 files changed

+164
-278
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ on:
33
push:
44
branches:
55
- develop
6+
- master
67
- release/**
78
pull_request:
89
workflow_dispatch:
@@ -136,6 +137,10 @@ jobs:
136137
# Note: These next three have to be checked as strings ('true'/'false')!
137138
is_develop: ${{ github.ref == 'refs/heads/develop' }}
138139
is_release: ${{ startsWith(github.ref, 'refs/heads/release/') }}
140+
is_gitflow_sync: |
141+
github.event_name == 'pull_request' &&
142+
(github.head_ref == 'refs/heads/develop' || github.head_ref == 'refs/heads/master') &&
143+
contains(steps.pr-labels.outputs.labels, ' Dev: Gitflow ')
139144
force_skip_cache:
140145
${{ github.event_name == 'pull_request' && contains(steps.pr-labels.outputs.labels, ' ci-skip-cache ') }}
141146

@@ -144,7 +149,9 @@ jobs:
144149
needs: job_get_metadata
145150
runs-on: ubuntu-20.04
146151
timeout-minutes: 15
147-
if: needs.job_get_metadata.outputs.changed_any_code == 'true' || github.event_name != 'pull_request'
152+
if: |
153+
needs.job_get_metadata.outputs.is_gitflow_sync == 'false' &&
154+
(needs.job_get_metadata.outputs.changed_any_code == 'true' || github.event_name != 'pull_request')
148155
steps:
149156
- name: 'Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})'
150157
uses: actions/checkout@v3

.github/workflows/gitflow-sync-develop.yml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ on:
1111
workflow_dispatch:
1212

1313
env:
14-
DEV_BRANCH: develop
14+
SOURCE_BRANCH: master
15+
TARGET_BRANCH: develop
1516

1617
jobs:
1718
main:
@@ -29,10 +30,13 @@ jobs:
2930
id: open-pr
3031
uses: repo-sync/pull-request@v2
3132
with:
32-
destination_branch: ${{ env.DEV_BRANCH }}
33-
pr_title: '[Gitflow] Merge ${{ github.ref_name }} into ${{ env.DEV_BRANCH }}'
34-
pr_body: 'Merge ${{ github.ref_name }} branch into ${{ env.DEV_BRANCH }}'
33+
source_branch: ${{ env.SOURCE_BRANCH }}
34+
destination_branch: ${{ env.TARGET_BRANCH }}
35+
pr_title: '[Gitflow] Merge ${{ env.SOURCE_BRANCH }} into ${{ env.TARGET_BRANCH }}'
36+
pr_body: 'Merge ${{ env.SOURCE_BRANCH }} branch into ${{ env.TARGET_BRANCH }}'
3537
pr_label: 'Dev: Gitflow'
38+
# This token is scoped to Daniel Griesser
39+
github_token: ${{ secrets.REPO_SCOPED_TOKEN }}
3640

3741
# https://github.com/marketplace/actions/enable-pull-request-automerge
3842
- name: Enable automerge for PR
@@ -44,9 +48,9 @@ jobs:
4448

4549
# https://github.com/marketplace/actions/auto-approve
4650
- name: Auto approve PR
51+
# Always skip this for now, until we got a proper bot setup
52+
if: steps.open-pr.outputs.pr_number != ''
4753
uses: hmarr/auto-approve-action@v3
4854
with:
4955
pull-request-number: ${{ steps.open-pr.outputs.pr_number }}
5056
review-message: 'Auto approved automated PR'
51-
# TODO: Use the token of some user here??
52-
# github-token: ${{ secrets.SOME_USERS_PAT }}

.github/workflows/gitflow-sync-master.yml

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
name: Gitflow - Sync develop into master
22
on:
33
push:
4-
branches:
5-
- develop
6-
paths:
7-
# We want to trigger this when ONLY the changlog is changed on develop, but nothing else
8-
- 'CHANGELOG.md'
9-
- '!packages'
10-
- '!**/*.js'
11-
- '!**/*.json'
12-
- '!**/*.ts'
13-
workflow_dispatch:
4+
pull_request:
5+
- types: [closed]
6+
- branches:
7+
- 'develop'
148

159
env:
1610
MAIN_BRANCH: master
@@ -19,6 +13,9 @@ jobs:
1913
main:
2014
name: Create PR develop->master
2115
runs-on: ubuntu-20.04
16+
if: |
17+
github.event.pull_request.merged == true
18+
&& startsWith(github.event.pull_request.title, "meta(changelog):")
2219
permissions:
2320
pull-requests: write
2421
contents: write
@@ -35,6 +32,8 @@ jobs:
3532
pr_title: '[Gitflow] Merge ${{ github.ref_name }} into ${{ env.MAIN_BRANCH }}'
3633
pr_body: 'Merge ${{ github.ref_name }} branch into ${{ env.MAIN_BRANCH }}'
3734
pr_label: 'Dev: Gitflow'
35+
# This token is scoped to Daniel Griesser
36+
github_token: ${{ secrets.REPO_SCOPED_TOKEN }}
3837

3938
# https://github.com/marketplace/actions/enable-pull-request-automerge
4039
- name: Enable automerge for PR
@@ -46,9 +45,18 @@ jobs:
4645

4746
# https://github.com/marketplace/actions/auto-approve
4847
- name: Auto approve PR
48+
# Always skip this for now, until we got a proper bot setup
49+
if: steps.open-pr.outputs.pr_number != ''
4950
uses: hmarr/auto-approve-action@v3
5051
with:
5152
pull-request-number: ${{ steps.open-pr.outputs.pr_number }}
5253
review-message: 'Auto approved automated PR'
53-
# TODO: Use the token of some user here??
54-
# github-token: ${{ secrets.SOME_USERS_PAT }}
54+
55+
skipped:
56+
runs-on: ubuntu-20.04
57+
if: |
58+
github.event.pull_request.merged == false
59+
|| startsWith(github.event.pull_request.title, "meta(changelog):") == false
60+
steps:
61+
- name: Sync skipped
62+
run: echo "OK"

CHANGELOG.md

Lines changed: 13 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.36.0
8+
9+
This Release re-introduces the accidentally removed but still deprecated `maskInputOptions` option for Session Replay.
10+
Furthermore, replays are now stopped instead of paused when a rate limit is encountered.
11+
12+
- feat(replay): Add back deprecated `maskInputOptions` (#6981)
13+
- feat(replay): Stop recording when hitting a rate limit (#7018)
14+
- fix(integrations): Report `BaseClient` integrations added after init (#7011)
15+
- fix(replay): Don't mangle private rrweb property (#7033)
16+
- fix(replay): Fix feature detection of PerformanceObserver (#7029)
17+
718
## 7.35.0
819

920
Session Replay is deprecating privacy options in favor of a more streamlined API. Please see the [Replay migration guide](https://github.com/getsentry/sentry-javascript/blob/master/packages/replay/MIGRATION.md) for further information.
@@ -27,6 +38,8 @@ Additionally, the following configuration options will no longer be configurable
2738
- fix(utils): Account for null prototype during normalization (#6925)
2839
- ref(replay): Log warning if sample rates are all undefined (#6959)
2940

41+
Work in this release contributed by @boblauer. Thank you for your contribution!
42+
3043
## 7.34.0
3144

3245
This release adds automatic injection of the Next.js SDK into serverside `app` directory bundles, allowing users to call the Sentry SDK in server components.

docs/publishing-a-release.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ _These steps are only relevant to Sentry employees when preparing and publishing
1717
## Updating the Changelog
1818

1919
1. Create a new branch.
20-
2. Run `git log --format="- %s"` and copy everything since the last release.
20+
2. Run `yarn changelog` and copy everything
2121
3. Create a new section in the changelog, deciding based on the changes whether it should be a minor bump or a patch release.
2222
4. Paste in the logs you copied earlier.
2323
5. Delete any which aren't user-facing changes.
24-
6. Alphabetize the rest.
2524
7. If any of the PRs are from external contributors, include underneath the commits `Work in this release contributed by <list of external contributors' GitHub usernames>. Thank you for your contributions!`. If there's only one external PR, don't forget to remove the final `s`. If there are three or more, use an Oxford comma. (It's in the Sentry styleguide!)
2625
8. Commit, push, and open a PR with the title `meta: Update changelog for <fill in relevant version here>` against `develop` branch.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"clean:all": "run-p clean:build clean:caches clean:deps",
2020
"codecov": "codecov",
2121
"fix": "lerna run fix",
22+
"changelog": "ts-node ./scripts/get-commit-list.ts",
2223
"link:yarn": "lerna exec yarn link",
2324
"lint": "lerna run lint",
2425
"lint:eslint": "lerna run lint:eslint",

packages/core/src/baseclient.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,10 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
435435
*/
436436
protected _prepareEvent(event: Event, hint: EventHint, scope?: Scope): PromiseLike<Event | null> {
437437
const options = this.getOptions();
438+
const integrations = Object.keys(this._integrations);
439+
if (!hint.integrations && integrations.length > 0) {
440+
hint.integrations = integrations;
441+
}
438442
return prepareEvent(options, event, hint, scope);
439443
}
440444

packages/core/src/utils/prepareEvent.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,10 @@ export function prepareEvent(
3232
event_id: event.event_id || hint.event_id || uuid4(),
3333
timestamp: event.timestamp || dateTimestampInSeconds(),
3434
};
35+
const integrations = hint.integrations || options.integrations.map(i => i.name);
3536

3637
applyClientOptions(prepared, options);
37-
applyIntegrationsMetadata(
38-
prepared,
39-
options.integrations.map(i => i.name),
40-
);
38+
applyIntegrationsMetadata(prepared, integrations);
4139

4240
// If we have scope given to us, use it as the base for further modifications.
4341
// This allows us to prevent unnecessary copying of data if `captureContext` is not provided.

packages/core/test/lib/base.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { dsnToString, logger, SentryError, SyncPromise } from '@sentry/utils';
44
import { Hub, makeSession, Scope } from '../../src';
55
import * as integrationModule from '../../src/integration';
66
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
7-
import { TestIntegration } from '../mocks/integration';
7+
import { AdHocIntegration, TestIntegration } from '../mocks/integration';
88
import { makeFakeTransport } from '../mocks/transport';
99

1010
const PUBLIC_DSN = 'https://username@domain/123';
@@ -678,6 +678,25 @@ describe('BaseClient', () => {
678678
});
679679
});
680680

681+
test('send all installed integrations in event sdk metadata', () => {
682+
expect.assertions(1);
683+
684+
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] });
685+
const client = new TestClient(options);
686+
client.setupIntegrations();
687+
client.addIntegration(new AdHocIntegration());
688+
689+
client.captureException(new Error('test exception'));
690+
691+
expect(TestClient.instance!.event).toEqual(
692+
expect.objectContaining({
693+
sdk: expect.objectContaining({
694+
integrations: expect.arrayContaining(['TestIntegration', 'AdHockIntegration']),
695+
}),
696+
}),
697+
);
698+
});
699+
681700
test('normalizes event with default depth of 3', () => {
682701
expect.assertions(1);
683702

packages/core/test/mocks/integration.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,13 @@ export class AddAttachmentTestIntegration implements Integration {
3636
});
3737
}
3838
}
39+
40+
export class AdHocIntegration implements Integration {
41+
public static id: string = 'AdHockIntegration';
42+
43+
public name: string = 'AdHockIntegration';
44+
45+
public setupOnce(): void {
46+
// Noop
47+
}
48+
}

packages/replay/src/integration.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export class Replay implements Integration {
6969
// eslint-disable-next-line deprecation/deprecation
7070
blockSelector,
7171
// eslint-disable-next-line deprecation/deprecation
72+
maskInputOptions,
73+
// eslint-disable-next-line deprecation/deprecation
7274
maskTextClass,
7375
// eslint-disable-next-line deprecation/deprecation
7476
maskTextSelector,
@@ -77,6 +79,7 @@ export class Replay implements Integration {
7779
}: ReplayConfiguration = {}) {
7880
this._recordingOptions = {
7981
maskAllInputs,
82+
maskInputOptions: { ...(maskInputOptions || {}), password: true },
8083
maskTextFn: maskFn,
8184
maskInputFn: maskFn,
8285

packages/replay/src/replay.ts

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import { EventType, record } from '@sentry-internal/rrweb';
33
import { captureException } from '@sentry/core';
44
import type { Breadcrumb, ReplayRecordingMode } from '@sentry/types';
5-
import type { RateLimits } from '@sentry/utils';
6-
import { disabledUntil, logger } from '@sentry/utils';
5+
import { logger } from '@sentry/utils';
76

87
import {
98
ERROR_CHECKOUT_TIME,
@@ -40,7 +39,6 @@ import { isExpired } from './util/isExpired';
4039
import { isSessionExpired } from './util/isSessionExpired';
4140
import { overwriteRecordDroppedEvent, restoreRecordDroppedEvent } from './util/monkeyPatchRecordDroppedEvent';
4241
import { sendReplay } from './util/sendReplay';
43-
import { RateLimitError } from './util/sendReplayRequest';
4442

4543
/**
4644
* The main replay container class, which holds all the state and methods for recording and sending replays.
@@ -476,8 +474,8 @@ export class ReplayContainer implements ReplayContainerInterface {
476474
this._handleException(err);
477475
}
478476

479-
// _performanceObserver //
480-
if (!('_performanceObserver' in WINDOW)) {
477+
// PerformanceObserver //
478+
if (!('PerformanceObserver' in WINDOW)) {
481479
return;
482480
}
483481

@@ -809,11 +807,6 @@ export class ReplayContainer implements ReplayContainerInterface {
809807
} catch (err) {
810808
this._handleException(err);
811809

812-
if (err instanceof RateLimitError) {
813-
this._handleRateLimit(err.rateLimits);
814-
return;
815-
}
816-
817810
// This means we retried 3 times, and all of them failed
818811
// In this case, we want to completely stop the replay - otherwise, we may get inconsistent segments
819812
this.stop();
@@ -873,29 +866,4 @@ export class ReplayContainer implements ReplayContainerInterface {
873866
saveSession(this.session);
874867
}
875868
}
876-
877-
/**
878-
* Pauses the replay and resumes it after the rate-limit duration is over.
879-
*/
880-
private _handleRateLimit(rateLimits: RateLimits): void {
881-
// in case recording is already paused, we don't need to do anything, as we might have already paused because of a
882-
// rate limit
883-
if (this.isPaused()) {
884-
return;
885-
}
886-
887-
const rateLimitEnd = disabledUntil(rateLimits, 'replay');
888-
const rateLimitDuration = rateLimitEnd - Date.now();
889-
890-
if (rateLimitDuration > 0) {
891-
__DEBUG_BUILD__ && logger.warn('[Replay]', `Rate limit hit, pausing replay for ${rateLimitDuration}ms`);
892-
this.pause();
893-
this._debouncedFlush.cancel();
894-
895-
setTimeout(() => {
896-
__DEBUG_BUILD__ && logger.info('[Replay]', 'Resuming replay after rate limit');
897-
this.resume();
898-
}, rateLimitDuration);
899-
}
900-
}
901869
}

packages/replay/src/types.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ export interface DeprecatedPrivacyOptions {
158158
* @deprecated Use `block` which accepts an array of CSS selectors
159159
*/
160160
blockClass?: RecordingOptions['blockClass'];
161+
/**
162+
* @deprecated Use `ignore` which accepts an array of CSS selectors
163+
*/
164+
ignoreClass?: RecordingOptions['ignoreClass'];
165+
/**
166+
* @deprecated Use `mask` which accepts an array of CSS selectors
167+
*/
168+
maskInputOptions?: RecordingOptions['maskInputOptions'];
161169
/**
162170
* @deprecated Use `mask` which accepts an array of CSS selectors
163171
*/
@@ -166,10 +174,6 @@ export interface DeprecatedPrivacyOptions {
166174
* @deprecated Use `mask` which accepts an array of CSS selectors
167175
*/
168176
maskTextSelector?: RecordingOptions['maskTextSelector'];
169-
/**
170-
* @deprecated Use `ignore` which accepts an array of CSS selectors
171-
*/
172-
ignoreClass?: RecordingOptions['ignoreClass'];
173177
}
174178

175179
export interface ReplayConfiguration

packages/replay/src/types/rrweb.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ export type recordOptions = {
3636
maskTextClass?: maskTextClass;
3737
maskTextSelector?: string;
3838
blockSelector?: string;
39+
maskInputOptions?: Record<string, boolean>;
3940
} & Record<string, unknown>;

packages/replay/src/util/getPrivacyOptions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { DeprecatedPrivacyOptions, ReplayIntegrationPrivacyOptions } from '../types';
22

3-
type GetPrivacyOptions = Required<Omit<ReplayIntegrationPrivacyOptions, 'maskFn'>> & DeprecatedPrivacyOptions;
3+
type GetPrivacyOptions = Required<Omit<ReplayIntegrationPrivacyOptions, 'maskFn'>> &
4+
Omit<DeprecatedPrivacyOptions, 'maskInputOptions'>;
45
interface GetPrivacyReturn {
56
maskTextSelector: string;
67
unmaskTextSelector: string;

0 commit comments

Comments
 (0)