Skip to content

Commit af50bee

Browse files
committed
Merge branch 'master' into joseph/webhooks
2 parents 8c6d2be + 7196fc7 commit af50bee

File tree

312 files changed

+8541
-4000
lines changed

Some content is hidden

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

312 files changed

+8541
-4000
lines changed

.github/CODEOWNERS

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,6 @@ tests/sentry/api/endpoints/test_organization_dashboard_widget_details.py @ge
368368
/src/sentry/toolbar/ @getsentry/replay-frontend @getsentry/replay-backend
369369
/tests/sentry/toolbar/ @getsentry/replay-frontend @getsentry/replay-backend
370370
/static/app/components/devtoolbar/ @getsentry/replay-frontend
371-
/src/sentry/middleware/devtoolbar.py @getsentry/replay-backend
372-
/tests/sentry/middleware/test_devtoolbar.py @getsentry/replay-backend
373371
## End of DevToolbar
374372

375373
## Codecov Merge UX

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export const typeAwareLintRules = {
4343
rules: {
4444
'@typescript-eslint/await-thenable': 'error',
4545
'@typescript-eslint/no-array-delete': 'error',
46+
'@typescript-eslint/no-base-to-string': 'error',
4647
'@typescript-eslint/no-for-in-array': 'error',
4748
'@typescript-eslint/no-unnecessary-type-assertion': 'error',
4849
'@typescript-eslint/prefer-optional-chain': 'error',

migrations_lockfile.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ remote_subscriptions: 0003_drop_remote_subscription
2121

2222
replays: 0005_drop_replay_index
2323

24-
sentry: 0896_org_level_access_not_null
24+
sentry: 0904_onboarding_task_project_id_idx
2525

2626
social_auth: 0002_default_auto_field
2727

2828
tempest: 0002_make_message_type_nullable
2929

30-
uptime: 0041_uptime_backfill_detector_grouphash
30+
uptime: 0042_extra_uptime_indexes
3131

32-
workflow_engine: 0060_rename_azure_devops_action_to_vsts
32+
workflow_engine: 0062_workflow_engine_missing_indexes

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@
182182
"@eslint/compat": "^1.2.7",
183183
"@eslint/eslintrc": "^3.3.0",
184184
"@eslint/js": "^9.22.0",
185+
"@mdx-js/loader": "^3.1.0",
185186
"@pmmmwh/react-refresh-webpack-plugin": "0.5.16",
186187
"@sentry/jest-environment": "6.0.0",
187188
"@sentry/profiling-node": "9.16.1",
@@ -250,11 +251,12 @@
250251
"fix:eslint": "eslint --fix",
251252
"fix:prettier": "prettier \"**/*.md\" \"**/*.yaml\" \"**/*.[jt]s(x)?\" --write --log-level=error",
252253
"dev": "(yarn check --verify-tree || yarn install --check-files) && sentry devserver",
253-
"dev-ui": "SENTRY_UI_DEV_ONLY=1 SENTRY_WEBPACK_PROXY_PORT=7999 SENTRY_UI_HOT_RELOAD=1 webpack serve",
254+
"dev-ui": "yarn dev-ui-rspack",
255+
"dev-ui-webpack": "SENTRY_UI_DEV_ONLY=1 SENTRY_WEBPACK_PROXY_PORT=7999 SENTRY_UI_HOT_RELOAD=1 webpack serve",
254256
"dev-ui-rspack": "SENTRY_UI_DEV_ONLY=1 SENTRY_WEBPACK_PROXY_PORT=7999 SENTRY_UI_HOT_RELOAD=1 rspack serve",
255257
"dev-ui-admin": "SENTRY_ADMIN_UI_DEV=1 yarn dev-ui",
256-
"dev-ui-admin-rspack": "SENTRY_ADMIN_UI_DEV=1 yarn dev-ui-rspack",
257258
"dev-ui-storybook": "STORYBOOK_TYPES=1 yarn dev-ui",
259+
"dev-ui-storybook-rspack": "STORYBOOK_TYPES=1 yarn dev-ui-rspack",
258260
"dev-acceptance": "NO_DEV_SERVER=1 NODE_ENV=development webpack --watch",
259261
"dev-acceptance-rspack": "NO_DEV_SERVER=1 NODE_ENV=development rspack --watch",
260262
"webpack-profile": "NO_TS_FORK=1 webpack --profile --json > stats.json",

requirements-dev-frozen.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ sortedcontainers==2.4.0
203203
soupsieve==2.3.2.post1
204204
sqlparse==0.5.0
205205
statsd==3.3.0
206-
stripe==5.5.0
206+
stripe==6.7.0
207207
structlog==22.1.0
208208
supervisor==4.2.5
209209
symbolic==12.14.1

requirements-frozen.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ snuba-sdk==3.0.43
140140
soupsieve==2.3.2.post1
141141
sqlparse==0.5.0
142142
statsd==3.3.0
143-
stripe==5.5.0
143+
stripe==6.7.0
144144
structlog==22.1.0
145145
symbolic==12.14.1
146146
tiktoken==0.8.0

requirements-getsentry.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ iso3166
1111
pycountry==17.5.14
1212
pyvat==1.3.15
1313
reportlab==4.4.0
14-
stripe==5.5.0
14+
stripe==6.7.0

rspack.config.ts

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
DevServer,
88
OptimizationSplitChunksCacheGroup,
99
RspackPluginInstance,
10+
RuleSetRule,
1011
} from '@rspack/core';
1112
import rspack from '@rspack/core';
1213
import ReactRefreshRspackPlugin from '@rspack/plugin-react-refresh';
@@ -170,6 +171,35 @@ for (const locale of supportedLocales) {
170171
};
171172
}
172173

174+
const swcReactLoaderConfig: RuleSetRule['options'] = {
175+
jsc: {
176+
experimental: {
177+
plugins: [
178+
[
179+
'@swc/plugin-emotion',
180+
{
181+
sourceMap: true,
182+
// The "dev-only" option does not seem to apply correctly
183+
autoLabel: DEV_MODE ? 'always' : 'never',
184+
},
185+
],
186+
],
187+
},
188+
parser: {
189+
syntax: 'typescript',
190+
tsx: true,
191+
},
192+
transform: {
193+
react: {
194+
runtime: 'automatic',
195+
development: DEV_MODE,
196+
refresh: DEV_MODE,
197+
importSource: '@emotion/react',
198+
},
199+
},
200+
},
201+
};
202+
173203
/**
174204
* Main Webpack config for Sentry React SPA.
175205
*/
@@ -217,34 +247,19 @@ const appConfig: Configuration = {
217247
test: /\.(js|jsx|ts|tsx)$/,
218248
exclude: /\/node_modules\//,
219249
loader: 'builtin:swc-loader',
220-
options: {
221-
jsc: {
222-
experimental: {
223-
plugins: [
224-
[
225-
'@swc/plugin-emotion',
226-
{
227-
sourceMap: true,
228-
// The "dev-only" option does not seem to apply correctly
229-
autoLabel: DEV_MODE ? 'always' : 'never',
230-
},
231-
],
232-
],
233-
},
234-
parser: {
235-
syntax: 'typescript',
236-
tsx: true,
237-
},
238-
transform: {
239-
react: {
240-
runtime: 'automatic',
241-
development: DEV_MODE,
242-
refresh: DEV_MODE,
243-
importSource: '@emotion/react',
244-
},
245-
},
250+
options: swcReactLoaderConfig,
251+
},
252+
{
253+
test: /\.mdx?$/,
254+
use: [
255+
{
256+
loader: 'builtin:swc-loader',
257+
options: swcReactLoaderConfig,
246258
},
247-
},
259+
{
260+
loader: '@mdx-js/loader',
261+
},
262+
],
248263
},
249264
{
250265
test: /\.po$/,

src/sentry/api/endpoints/group_ai_autofix.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ class GroupAutofixEndpoint(GroupAiEndpoint):
3535
enforce_rate_limit = True
3636
rate_limits = {
3737
"POST": {
38-
RateLimitCategory.IP: RateLimit(limit=10, window=60),
39-
RateLimitCategory.USER: RateLimit(limit=10, window=60),
40-
RateLimitCategory.ORGANIZATION: RateLimit(limit=10, window=60),
38+
RateLimitCategory.IP: RateLimit(limit=5, window=60),
39+
RateLimitCategory.USER: RateLimit(limit=5, window=60),
40+
RateLimitCategory.ORGANIZATION: RateLimit(limit=20, window=60 * 60), # 1 hour
4141
},
4242
"GET": {
4343
RateLimitCategory.IP: RateLimit(limit=256, window=60),

src/sentry/api/endpoints/project_rule_details.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ def put(self, request: Request, project, rule) -> Response:
245245
"name": data["name"],
246246
"environment": data.get("environment"),
247247
"project": project,
248+
"project_id": project.id,
248249
"action_match": data["actionMatch"],
249250
"filter_match": data.get("filterMatch"),
250251
"conditions": conditions,

src/sentry/api/endpoints/project_rules.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,7 @@ def post(self, request: Request, project) -> Response:
800800
"name": data["name"],
801801
"environment": data.get("environment"),
802802
"project": project,
803+
"project_id": project.id,
803804
"action_match": data["actionMatch"],
804805
"filter_match": data.get("filterMatch"),
805806
"conditions": conditions,

src/sentry/api/helpers/default_symbol_sources.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
DEFAULT_SYMBOL_SOURCES = {
55
"electron": ["ios", "microsoft", "electron"],
66
"javascript-electron": ["ios", "microsoft", "electron"],
7-
"unity": ["unity"],
7+
"unity": ["unity", "nvidia", "ubuntu"],
8+
"unreal": ["nvidia", "ubuntu"],
9+
"godot": ["nvidia", "ubuntu"],
810
}
911

1012

src/sentry/api/serializers/models/rule.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ def _fetch_workflow_last_triggered(self, item_list: Sequence[Workflow]) -> dict[
422422
result_qs = reduce(
423423
lambda q1, q2: q1.union(q2),
424424
[
425-
WorkflowFireHistory.objects.filter(workflow=item, has_fired_actions=True)
425+
WorkflowFireHistory.objects.filter(workflow=item)
426426
.order_by("-date_added")
427427
.values("workflow_id", "date_added")[:1]
428428
for item in item_list

src/sentry/api/urls.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2914,7 +2914,6 @@ def create_group_urls(name_prefix: str) -> list[URLPattern | URLResolver]:
29142914
ProjectSeerPreferencesEndpoint.as_view(),
29152915
name="sentry-api-0-project-seer-preferences",
29162916
),
2917-
*workflow_urls.project_urlpatterns,
29182917
]
29192918

29202919
TEAM_URLS = [

src/sentry/conf/server.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3355,7 +3355,6 @@ def custom_parameter_sort(parameter: dict) -> tuple[str, int]:
33553355
SEER_AUTOFIX_URL = SEER_DEFAULT_URL # for local development, these share a URL
33563356

33573357
SEER_GROUPING_URL = SEER_DEFAULT_URL # for local development, these share a URL
3358-
SEER_GROUPING_TIMEOUT = 1
33593358

33603359
SEER_GROUPING_BACKFILL_URL = SEER_DEFAULT_URL
33613360

src/sentry/consumers/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,11 @@ def ingest_transactions_options() -> list[click.Option]:
424424
default=100,
425425
help="The number of segments to download from redis at once. Defaults to 100.",
426426
),
427+
click.Option(
428+
["--max-memory-percentage", "max_memory_percentage"],
429+
default=1.0,
430+
help="Maximum memory usage of the Redis cluster in % (0.0-1.0) before the consumer backpressures.",
431+
),
427432
*multiprocessing_options(default_max_batch_size=100),
428433
],
429434
},

src/sentry/data_export/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class ExportedData(Model):
3737

3838
organization = FlexibleForeignKey("sentry.Organization")
3939
user_id = HybridCloudForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete="SET_NULL")
40-
file_id = BoundedBigIntegerField(null=True)
40+
file_id = BoundedBigIntegerField(null=True, db_index=True)
4141
date_added = models.DateTimeField(default=timezone.now)
4242
date_finished = models.DateTimeField(null=True)
4343
date_expired = models.DateTimeField(null=True, db_index=True)
@@ -161,7 +161,7 @@ class ExportedDataBlob(Model):
161161
__relocation_scope__ = RelocationScope.Excluded
162162

163163
data_export = FlexibleForeignKey("sentry.ExportedData")
164-
blob_id = BoundedBigIntegerField()
164+
blob_id = BoundedBigIntegerField(db_index=True)
165165
offset = BoundedBigIntegerField()
166166

167167
class Meta:

src/sentry/features/temporary.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,8 @@ def register_temporary_features(manager: FeatureManager):
502502
manager.add("organizations:jira-paginated-projects", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
503503
# Enable single trace summary
504504
manager.add("organizations:single-trace-summary", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
505+
# Enable users to connect many Sentry orgs to a single Github org
506+
manager.add("organizations:github-multi-org", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
505507
# Enable Relay extracting logs from breadcrumbs for a project.
506508
manager.add("projects:ourlogs-breadcrumb-extraction", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
507509

@@ -529,8 +531,6 @@ def register_temporary_features(manager: FeatureManager):
529531
manager.add("projects:use-eap-spans-for-metrics-explorer", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
530532
# Enable tagging span with whether or not we should ingest it in the EAP
531533
manager.add("projects:ingest-spans-in-eap", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
532-
# Enables automatically triggering issue summary on alerts
533-
manager.add("projects:trigger-issue-summary-on-alerts", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
534534
# Enable num events in an issue debugging
535535
manager.add("projects:num-events-issue-debugging", ProjectFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
536536

src/sentry/grouping/api.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
DefaultGroupingComponent,
1717
SystemGroupingComponent,
1818
)
19-
from sentry.grouping.enhancer import LATEST_VERSION, Enhancements, get_enhancements_version
19+
from sentry.grouping.enhancer import Enhancements, get_enhancements_version
2020
from sentry.grouping.enhancer.exceptions import InvalidEnhancerConfig
2121
from sentry.grouping.strategies.base import DEFAULT_GROUPING_ENHANCEMENTS_BASE, GroupingContext
2222
from sentry.grouping.strategies.configurations import CONFIGURATIONS
@@ -93,14 +93,15 @@ def _get_enhancements(self, project: Project) -> str:
9393

9494
config_id = self._get_config_id(project)
9595
enhancements_base = CONFIGURATIONS[config_id].enhancements_base
96+
enhancements_version = get_enhancements_version(project, config_id)
9697

9798
# Instead of parsing and dumping out config here, we can make a
9899
# shortcut
99100
from sentry.utils.cache import cache
100101
from sentry.utils.hashlib import md5_text
101102

102103
cache_prefix = self.cache_prefix
103-
cache_prefix += f"{LATEST_VERSION}:"
104+
cache_prefix += f"{enhancements_version}:"
104105
cache_key = (
105106
cache_prefix
106107
+ md5_text(
@@ -124,7 +125,7 @@ def _get_enhancements(self, project: Project) -> str:
124125
enhancements = Enhancements.from_rules_text(
125126
enhancements_string,
126127
bases=[enhancements_base] if enhancements_base else [],
127-
version=get_enhancements_version(project, config_id),
128+
version=enhancements_version,
128129
referrer="project_rules",
129130
).base64_string
130131
except InvalidEnhancerConfig:

src/sentry/grouping/strategies/base.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
FrameGroupingComponent,
1212
StacktraceGroupingComponent,
1313
)
14-
from sentry.grouping.enhancer import Enhancements
14+
from sentry.grouping.enhancer import ENHANCEMENT_BASES, Enhancements
15+
from sentry.grouping.enhancer.exceptions import InvalidEnhancerConfig
1516
from sentry.interfaces.base import Interface
1617
from sentry.interfaces.exception import SingleException
1718
from sentry.interfaces.stacktrace import Frame, Stacktrace
@@ -305,9 +306,18 @@ def __init__(self, enhancements: str | None = None, **extra: Any):
305306
if enhancements is None:
306307
enhancements_instance = Enhancements.from_rules_text("", referrer="strategy_config")
307308
else:
308-
enhancements_instance = Enhancements.from_base64_string(
309-
enhancements, referrer="strategy_config"
310-
)
309+
# If the enhancements string has been loaded from an existing event, it may be from an
310+
# obsolete enhancements version, in which case we just use the default enhancements for
311+
# this grouping config
312+
try:
313+
enhancements_instance = Enhancements.from_base64_string(
314+
enhancements, referrer="strategy_config"
315+
)
316+
except InvalidEnhancerConfig:
317+
enhancements_instance = ENHANCEMENT_BASES[
318+
self.enhancements_base or DEFAULT_GROUPING_ENHANCEMENTS_BASE
319+
]
320+
311321
self.enhancements = enhancements_instance
312322

313323
def __repr__(self) -> str:

src/sentry/hybridcloud/rpc/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import threading
66
from collections.abc import Callable, Iterable, Mapping
77
from enum import Enum
8-
from typing import Any, Generic, Protocol, Self, TypeVar, cast
8+
from typing import Any, Generic, Self, TypeVar, cast
99

1010
import pydantic
1111
from django.db import router, transaction
@@ -99,10 +99,6 @@ def serialize_by_field_name(
9999
return cls(**fields)
100100

101101

102-
class RpcModelProtocolMeta(type(RpcModel), type(Protocol)): # type: ignore[misc]
103-
"""A unifying metaclass for RpcModel classes that also implement a Protocol."""
104-
105-
106102
ServiceInterface = TypeVar("ServiceInterface")
107103

108104

src/sentry/incidents/models/alert_rule.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ class AlertRule(Model):
220220
)
221221
description = models.CharField(max_length=1000, null=True)
222222
detection_type = models.CharField(
223+
max_length=32,
223224
default=AlertRuleDetectionType.STATIC,
224225
db_default=AlertRuleDetectionType.STATIC,
225226
choices=AlertRuleDetectionType.choices,

0 commit comments

Comments
 (0)