Skip to content

Commit f5a1b24

Browse files
authored
Merge branch 'master' into jferg/remove-internal-multi-choice
2 parents a0e6e52 + 31b7777 commit f5a1b24

File tree

118 files changed

+3136
-796
lines changed

Some content is hidden

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

118 files changed

+3136
-796
lines changed

.github/CODEOWNERS

+7-5
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ yarn.lock @getsentry/owners-js-de
171171
/static/app/views/alerts/ @getsentry/alerts-notifications
172172
/static/app/views/alerts/rules/uptime @getsentry/crons
173173
/static/app/views/releases/ @getsentry/alerts-notifications
174+
/static/app/views/releases/drawer/ @getsentry/replay-frontend
175+
/static/app/views/releases/releaseBubbles/ @getsentry/replay-frontend
174176
/src/sentry/rules/processing/delayed_processing.py @getsentry/alerts-notifications
175177

176178
/static/app/views/settings/account/notifications/ @getsentry/alerts-notifications
@@ -329,11 +331,11 @@ tests/sentry/api/endpoints/test_organization_dashboard_widget_details.py @ge
329331

330332

331333
## Replays
332-
/static/app/components/replays/ @getsentry/replay-frontend
333-
/static/app/utils/replays/ @getsentry/replay-frontend
334-
/static/app/views/replays/ @getsentry/replay-frontend
335-
/src/sentry/replays/ @getsentry/replay-backend
336-
/tests/sentry/replays/ @getsentry/replay-backend
334+
/static/app/components/replays/ @getsentry/replay-frontend
335+
/static/app/utils/replays/ @getsentry/replay-frontend
336+
/static/app/views/replays/ @getsentry/replay-frontend
337+
/src/sentry/replays/ @getsentry/replay-backend
338+
/tests/sentry/replays/ @getsentry/replay-backend
337339
## End of Replays
338340

339341

migrations_lockfile.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ remote_subscriptions: 0003_drop_remote_subscription
1717

1818
replays: 0004_index_together
1919

20-
sentry: 0842_create_organization_member_invite_table
20+
sentry: 0843_make_groupsearchview_postition_nullable_for_deletion
2121

2222
social_auth: 0002_default_auto_field
2323

requirements-base.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ requests>=2.32.3
6565
rfc3339-validator>=0.1.2
6666
rfc3986-validator>=0.1.1
6767
# [end] jsonschema format validators
68-
sentry-arroyo>=2.19.9
68+
sentry-arroyo>=2.20.0
6969
sentry-kafka-schemas>=1.1.2
7070
sentry-ophio==1.0.0
7171
sentry-protos>=0.1.62

requirements-dev-frozen.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ click==8.1.7
2929
click-didyoumean==0.3.0
3030
click-plugins==1.1.1
3131
click-repl==0.3.0
32-
confluent-kafka==2.3.0
32+
confluent-kafka==2.8.0
3333
covdefaults==2.3.0
3434
coverage==7.6.4
3535
cronsim==2.6
@@ -180,7 +180,7 @@ rpds-py==0.20.0
180180
rsa==4.8
181181
s3transfer==0.10.0
182182
selenium==4.16.0
183-
sentry-arroyo==2.19.9
183+
sentry-arroyo==2.20.0
184184
sentry-cli==2.16.0
185185
sentry-covdefaults-disable-branch-coverage==1.0.2
186186
sentry-devenv==1.16.0

requirements-frozen.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ click==8.1.7
2626
click-didyoumean==0.3.0
2727
click-plugins==1.1.1
2828
click-repl==0.3.0
29-
confluent-kafka==2.3.0
29+
confluent-kafka==2.8.0
3030
cronsim==2.6
3131
cryptography==43.0.1
3232
cssselect==1.0.3
@@ -123,7 +123,7 @@ rfc3986-validator==0.1.1
123123
rpds-py==0.20.0
124124
rsa==4.8
125125
s3transfer==0.10.0
126-
sentry-arroyo==2.19.9
126+
sentry-arroyo==2.20.0
127127
sentry-forked-email-reply-parser==0.5.12.post1
128128
sentry-kafka-schemas==1.1.2
129129
sentry-ophio==1.0.0

src/sentry/api/endpoints/group_ai_summary.py

+19-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from sentry.api.bases.group import GroupEndpoint
1919
from sentry.api.serializers import EventSerializer, serialize
2020
from sentry.api.serializers.rest_framework.base import convert_dict_key_case, snake_to_camel_case
21+
from sentry.autofix.utils import get_autofix_state
2122
from sentry.constants import ObjectStatus
2223
from sentry.eventstore.models import Event, GroupEvent
2324
from sentry.models.group import Group
@@ -240,15 +241,24 @@ def post(self, request: Request, group: Group) -> Response:
240241
issue_summary = self._generate_fixability_score(group.id)
241242

242243
if issue_summary.scores.is_fixable:
243-
with sentry_sdk.start_span(op="ai_summary.trigger_autofix"):
244-
response = trigger_autofix(
245-
group=group, event_id=event.event_id, user=request.user
246-
)
247-
248-
if response.status_code != 202:
249-
# If autofix trigger fails, we don't cache to let it error and we can run again
250-
# This is only temporary for when we're testing this internally.
251-
return response
244+
with sentry_sdk.start_span(op="ai_summary.get_autofix_state"):
245+
autofix_state = get_autofix_state(group_id=group.id)
246+
247+
if (
248+
not autofix_state
249+
): # Only trigger autofix if we don't have an autofix on this issue already.
250+
with sentry_sdk.start_span(op="ai_summary.trigger_autofix"):
251+
response = trigger_autofix(
252+
group=group,
253+
event_id=event.event_id,
254+
user=request.user,
255+
auto_run_source="issue_summary_fixability",
256+
)
257+
258+
if response.status_code != 202:
259+
# If autofix trigger fails, we don't cache to let it error and we can run again
260+
# This is only temporary for when we're testing this internally.
261+
return response
252262

253263
summary_dict = issue_summary.dict()
254264
summary_dict["event_id"] = event.event_id

src/sentry/api/event_search.py

+54-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from collections.abc import Callable, Generator, Mapping, Sequence
77
from dataclasses import asdict, dataclass, field
88
from datetime import datetime
9-
from typing import TYPE_CHECKING, Any, Literal, NamedTuple, TypeIs, Union
9+
from typing import TYPE_CHECKING, Any, Literal, NamedTuple, TypeIs, Union, overload
1010

1111
from django.utils.functional import cached_property
1212
from parsimonious.exceptions import IncompleteParseError
@@ -574,8 +574,8 @@ def __str__(self) -> str:
574574
return f"{self.key.name}{self.operator}{self.value.raw_value}"
575575

576576

577-
@dataclass
578-
class SearchConfig:
577+
@dataclass # pycqa/pycodestyle#1277
578+
class SearchConfig[TAllowBoolean: (Literal[True], Literal[False]) = Literal[True]]: # noqa: E251
579579
"""
580580
Configures how the search parser interprets a search query
581581
"""
@@ -604,7 +604,7 @@ class SearchConfig:
604604
is_filter_translation: Mapping[str, tuple[str, Any]] = field(default_factory=dict)
605605

606606
# Enables boolean filtering (AND / OR)
607-
allow_boolean = True
607+
allow_boolean: TAllowBoolean = True # type: ignore[assignment] # python/mypy#18812
608608

609609
# Allows us to specify an allowlist of keys we will accept for this search.
610610
# If empty, allow all keys.
@@ -619,8 +619,32 @@ class SearchConfig:
619619
# Whether to wrap free_text_keys in asterisks
620620
wildcard_free_text: bool = False
621621

622+
@overload
622623
@classmethod
623-
def create_from(cls, search_config: SearchConfig, **overrides):
624+
def create_from[
625+
TBool: (Literal[True], Literal[False])
626+
](
627+
cls: type[SearchConfig[Any]],
628+
search_config: SearchConfig[Any],
629+
*,
630+
allow_boolean: TBool,
631+
**overrides: Any,
632+
) -> SearchConfig[TBool]: ...
633+
634+
@overload
635+
@classmethod
636+
def create_from[
637+
TBool: (Literal[True], Literal[False])
638+
](
639+
cls: type[SearchConfig[Any]],
640+
search_config: SearchConfig[TBool],
641+
**overrides: Any,
642+
) -> SearchConfig[TBool]: ...
643+
644+
@classmethod
645+
def create_from(
646+
cls: type[SearchConfig[Any]], search_config: SearchConfig[Any], **overrides: Any
647+
) -> SearchConfig[Any]:
624648
config = cls(**asdict(search_config))
625649
for key, val in overrides.items():
626650
setattr(config, key, val)
@@ -632,7 +656,7 @@ class SearchVisitor(NodeVisitor):
632656

633657
def __init__(
634658
self,
635-
config: SearchConfig,
659+
config: SearchConfig[Any],
636660
params: ParamsType | None = None,
637661
get_field_type: Callable[[str], str | None] | None = None,
638662
get_function_result_type: Callable[[str], str | None] | None = None,
@@ -1330,16 +1354,36 @@ def generic_visit(self, node, children):
13301354
QueryToken = Union[SearchFilter, AggregateFilter, QueryOp, ParenExpression]
13311355

13321356

1357+
@overload
1358+
def parse_search_query(
1359+
query: str,
1360+
*,
1361+
config: SearchConfig[Literal[False]],
1362+
params=None,
1363+
get_field_type: Callable[[str], str | None] | None = None,
1364+
get_function_result_type: Callable[[str], str | None] | None = None,
1365+
) -> Sequence[SearchFilter | AggregateFilter]: ...
1366+
1367+
1368+
@overload
1369+
def parse_search_query(
1370+
query: str,
1371+
*,
1372+
config: SearchConfig[Literal[True]] | None = None,
1373+
params=None,
1374+
get_field_type: Callable[[str], str | None] | None = None,
1375+
get_function_result_type: Callable[[str], str | None] | None = None,
1376+
) -> Sequence[QueryToken]: ...
1377+
1378+
13331379
def parse_search_query(
13341380
query: str,
13351381
*,
1336-
config: SearchConfig | None = None,
1382+
config: SearchConfig[Any] | None = None,
13371383
params=None,
13381384
get_field_type: Callable[[str], str | None] | None = None,
13391385
get_function_result_type: Callable[[str], str | None] | None = None,
1340-
) -> list[
1341-
SearchFilter
1342-
]: # TODO: use the `Sequence[QueryToken]` type and update the code that fails type checking.
1386+
) -> Sequence[QueryToken]:
13431387
if config is None:
13441388
config = default_config
13451389

src/sentry/api/helpers/group_index/index.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from rest_framework.response import Response
1313

1414
from sentry import features, search
15-
from sentry.api.event_search import SearchFilter
15+
from sentry.api.event_search import AggregateFilter, SearchFilter
1616
from sentry.api.issue_search import convert_query_values, parse_search_query
1717
from sentry.api.serializers import serialize
1818
from sentry.constants import DEFAULT_SORT_OPTION
@@ -53,7 +53,7 @@ def parse_and_convert_issue_search_query(
5353
projects: Sequence[Project],
5454
environments: Sequence[Environment] | None,
5555
user: User | AnonymousUser,
56-
) -> Sequence[SearchFilter]:
56+
) -> Sequence[SearchFilter | AggregateFilter]:
5757
try:
5858
search_filters = convert_query_values(
5959
parse_search_query(query), projects, user, environments
@@ -160,7 +160,7 @@ def build_query_params_from_request(
160160

161161
def validate_search_filter_permissions(
162162
organization: Organization,
163-
search_filters: Sequence[SearchFilter],
163+
search_filters: Sequence[AggregateFilter | SearchFilter],
164164
user: User | AnonymousUser,
165165
) -> None:
166166
"""
@@ -178,7 +178,7 @@ def validate_search_filter_permissions(
178178

179179
for search_filter in search_filters:
180180
for feature_condition, feature_name in advanced_search_features:
181-
if feature_condition(search_filter):
181+
if isinstance(search_filter, SearchFilter) and feature_condition(search_filter):
182182
advanced_search_feature_gated.send_robust(
183183
user=user, organization=organization, sender=validate_search_filter_permissions
184184
)

src/sentry/api/issue_search.py

+12
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,18 @@ def convert_query_values(
273273
) -> list[SearchFilter]: ...
274274

275275

276+
# maintain a specific subtype of QueryToken union
277+
@overload
278+
def convert_query_values(
279+
search_filters: Sequence[AggregateFilter | SearchFilter],
280+
projects: Sequence[Project],
281+
user: User | RpcUser | AnonymousUser | None,
282+
environments: Sequence[Environment] | None,
283+
value_converters=value_converters,
284+
allow_aggregate_filters=False,
285+
) -> Sequence[AggregateFilter | SearchFilter]: ...
286+
287+
276288
@overload
277289
def convert_query_values(
278290
search_filters: Sequence[QueryToken],

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class GroupSearchViewSerializerResponse(TypedDict):
1313
name: str
1414
query: str
1515
querySort: SORT_LITERALS
16-
position: int
1716
projects: list[int]
1817
isAllProjects: bool
1918
environments: list[str]
@@ -23,6 +22,10 @@ class GroupSearchViewSerializerResponse(TypedDict):
2322
dateUpdated: str
2423

2524

25+
class GroupSearchViewStarredSerializerResponse(GroupSearchViewSerializerResponse):
26+
position: int
27+
28+
2629
@register(GroupSearchView)
2730
class GroupSearchViewSerializer(Serializer):
2831
def __init__(self, *args, **kwargs):
@@ -67,7 +70,6 @@ def serialize(self, obj, attrs, user, **kwargs) -> GroupSearchViewSerializerResp
6770
"name": obj.name,
6871
"query": obj.query,
6972
"querySort": obj.query_sort,
70-
"position": obj.position,
7173
"projects": projects,
7274
"isAllProjects": is_all_projects,
7375
"environments": obj.environments,
@@ -86,7 +88,7 @@ def __init__(self, *args, **kwargs):
8688
self.organization = kwargs.pop("organization", None)
8789
super().__init__(*args, **kwargs)
8890

89-
def serialize(self, obj, attrs, user, **kwargs) -> GroupSearchViewSerializerResponse:
91+
def serialize(self, obj, attrs, user, **kwargs) -> GroupSearchViewStarredSerializerResponse:
9092
serialized_view: GroupSearchViewSerializerResponse = serialize(
9193
obj.group_search_view,
9294
user,

src/sentry/features/temporary.py

+2
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,8 @@ def register_temporary_features(manager: FeatureManager):
483483
manager.add("organizations:workflow-engine-issue-alert-dual-write", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
484484
# Enable workflow engine for issue alerts
485485
manager.add("organizations:workflow-engine-process-workflows", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
486+
# Enable logging to debug workflow engine process workflows
487+
manager.add("organizations:workflow-engine-process-workflows-logs", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
486488
# Enable firing actions for workflow engine issue alerts
487489
manager.add("organizations:workflow-engine-trigger-actions", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
488490
# Enable dual writing for metric alert issues (see: alerts create issues)

0 commit comments

Comments
 (0)