Skip to content

Commit 083f132

Browse files
committed
Merge branch 'master' into zc/add-back-in-actor-constraints-idempotent
2 parents 1132203 + cd5438b commit 083f132

File tree

54 files changed

+1181
-637
lines changed

Some content is hidden

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

54 files changed

+1181
-637
lines changed

migrations_lockfile.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ To resolve this, rebase against latest master and regenerate your migration. Thi
66
will then be regenerated, and you should be able to merge without conflicts.
77

88
nodestore: 0002_nodestore_no_dictfield
9-
sentry: 0416_add_actor_constraints
9+
sentry: 0418_add_actor_constraints
1010
social_auth: 0001_initial

src/sentry/api/endpoints/notifications/notification_actions_available.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@
22
from rest_framework.response import Response
33

44
from sentry.api.base import region_silo_endpoint
5-
from sentry.api.bases.organization_flag import FlaggedOrganizationEndpoint
5+
from sentry.api.bases.organization import OrganizationEndpoint
66
from sentry.constants import ObjectStatus
77
from sentry.models.notificationaction import NotificationAction
88
from sentry.models.organization import Organization
99
from sentry.services.hybrid_cloud.integration import integration_service
1010

1111

1212
@region_silo_endpoint
13-
class NotificationActionsAvailableEndpoint(FlaggedOrganizationEndpoint):
14-
feature_flags = ["organizations:notification-actions"]
15-
13+
class NotificationActionsAvailableEndpoint(OrganizationEndpoint):
1614
def get(self, request: Request, organization: Organization) -> Response:
1715
"""
1816
Responds with a payload serialized directly from running the 'serialize_available' methods

src/sentry/api/endpoints/notifications/notification_actions_details.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from sentry import audit_log
99
from sentry.api.base import region_silo_endpoint
10-
from sentry.api.bases.organization_flag import FlaggedOrganizationEndpoint
10+
from sentry.api.bases.organization import OrganizationEndpoint
1111
from sentry.api.exceptions import ResourceDoesNotExist
1212
from sentry.api.serializers import serialize
1313
from sentry.api.serializers.rest_framework.notification_action import NotificationActionSerializer
@@ -18,16 +18,14 @@
1818

1919

2020
@region_silo_endpoint
21-
class NotificationActionsDetailsEndpoint(FlaggedOrganizationEndpoint):
21+
class NotificationActionsDetailsEndpoint(OrganizationEndpoint):
2222
"""
2323
Manages a single NotificationAction via the action_id passed in the path.
2424
GET: Returns the serialized NotificationAction
2525
PUT: Update the entire NotificationAction, overwriting previous values
2626
DELETE: Delete the NotificationAction
2727
"""
2828

29-
feature_flags = ["organizations:notification-actions"]
30-
3129
def convert_args(self, request: Request, action_id: int, *args, **kwargs):
3230
parsed_args, parsed_kwargs = super().convert_args(request, *args, **kwargs)
3331
organization = parsed_kwargs["organization"]

src/sentry/api/endpoints/notifications/notification_actions_index.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from sentry import audit_log
1010
from sentry.api.base import region_silo_endpoint
11-
from sentry.api.bases.organization_flag import FlaggedOrganizationEndpoint
11+
from sentry.api.bases.organization import OrganizationEndpoint
1212
from sentry.api.paginator import OffsetPaginator
1313
from sentry.api.serializers.base import serialize
1414
from sentry.api.serializers.rest_framework.notification_action import NotificationActionSerializer
@@ -19,15 +19,13 @@
1919

2020

2121
@region_silo_endpoint
22-
class NotificationActionsIndexEndpoint(FlaggedOrganizationEndpoint):
22+
class NotificationActionsIndexEndpoint(OrganizationEndpoint):
2323
"""
2424
View existing NotificationActions or create a new one.
2525
GET: Returns paginated, serialized NotificationActions for an organization
2626
POST: Create a new NotificationAction
2727
"""
2828

29-
feature_flags = ["organizations:notification-actions"]
30-
3129
def get(self, request: Request, organization: Organization) -> Response:
3230
queryset = NotificationAction.objects.filter(organization_id=organization.id)
3331
# If a project query is specified, filter out non-project-specific actions

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import re
34
from collections import defaultdict
45
from datetime import datetime
56
from typing import Any, Sequence
@@ -27,6 +28,7 @@
2728
CRASH_FILE_TYPES = {"event.minidump"}
2829
RESERVED_KEYS = frozenset(["user", "sdk", "device", "contexts"])
2930
FORMATTED_BREADCRUMB_CATEGORIES = frozenset(["query", "sql.query"])
31+
SQL_DOUBLEQUOTES_REGEX = re.compile(r"\"([a-zA-Z0-9_]+?)\"")
3032

3133

3234
def get_crash_files(events):
@@ -370,6 +372,9 @@ def _get_perf_problem(self, attrs):
370372
converted_problem["issueType"] = get_group_type_by_type_id(issue_type).slug
371373
return converted_problem
372374

375+
def _remove_doublequotes(self, message: str):
376+
return SQL_DOUBLEQUOTES_REGEX.sub(r"\1", message)
377+
373378
def _format_breadcrumb_messages(
374379
self, event_data: dict[str, Any], event: Event | GroupEvent, user: User
375380
):
@@ -389,8 +394,13 @@ def _format_breadcrumb_messages(
389394
breadcrumb_item["messageFormat"] = "sql"
390395
breadcrumb_item["messageRaw"] = breadcrumb_item["message"]
391396
breadcrumb_item["message"] = sqlparse.format(
392-
breadcrumb_item["message"], reindent_aligned=True
397+
breadcrumb_item["message"], reindent=True, wrap_after=80
393398
)
399+
if breadcrumb_item["message"] != breadcrumb_item["messageRaw"]:
400+
breadcrumb_item["message"] = self._remove_doublequotes(
401+
breadcrumb_item["message"]
402+
)
403+
394404
return event_data
395405
except Exception as exc:
396406
sentry_sdk.capture_exception(exc)

src/sentry/conf/server.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,8 +1304,6 @@ def SOCIAL_AUTH_DEFAULT_USERNAME():
13041304
"organizations:starfish-view": False,
13051305
# Enable Session Stats down to a minute resolution
13061306
"organizations:minute-resolution-sessions": True,
1307-
# Enable access to Notification Actions and their endpoints
1308-
"organizations:notification-actions": False,
13091307
# Notify all project members when fallthrough is disabled, instead of just the auto-assignee
13101308
"organizations:notification-all-recipients": False,
13111309
# Enable performance issues dev options, includes changing detection thresholds and other parts of issues that we're using for development.

src/sentry/deletions/defaults/project.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ def get_child_relations(self, instance):
3232
models.GroupShare,
3333
models.GroupSubscription,
3434
models.LatestAppConnectBuildsCheck,
35-
Monitor,
3635
models.ProjectBookmark,
3736
models.ProjectKey,
3837
models.ProjectTeam,
@@ -55,6 +54,7 @@ def get_child_relations(self, instance):
5554
for m in model_list
5655
]
5756
)
57+
relations.append(ModelRelation(Monitor, {"project_id": instance.id}))
5858
relations.append(ModelRelation(models.Group, {"project_id": instance.id}))
5959
relations.append(
6060
ModelRelation(

src/sentry/features/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@
113113
default_manager.add("organizations:device-class-synthesis", OrganizationFeature, FeatureHandlerStrategy.INTERNAL)
114114
default_manager.add("organizations:monitors", OrganizationFeature, FeatureHandlerStrategy.REMOTE)
115115
default_manager.add("organizations:new-weekly-report", OrganizationFeature, FeatureHandlerStrategy.REMOTE)
116-
default_manager.add("organizations:notification-actions", OrganizationFeature, FeatureHandlerStrategy.REMOTE)
117116
default_manager.add("organizations:notification-all-recipients", OrganizationFeature, FeatureHandlerStrategy.REMOTE)
118117
default_manager.add("organizations:onboarding", OrganizationFeature, FeatureHandlerStrategy.INTERNAL) # Only enabled in sentry.io to enable onboarding flows.
119118
default_manager.add("organizations:org-subdomains", OrganizationFeature, FeatureHandlerStrategy.INTERNAL)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Generated by Django 2.2.28 on 2023-04-06 21:30
2+
3+
from django.db import migrations
4+
5+
from sentry.new_migrations.migrations import CheckedMigration
6+
7+
8+
class Migration(CheckedMigration):
9+
# This flag is used to mark that a migration shouldn't be automatically run in production. For
10+
# the most part, this should only be used for operations where it's safe to run the migration
11+
# after your code has deployed. So this should not be used for most operations that alter the
12+
# schema of a table.
13+
# Here are some things that make sense to mark as dangerous:
14+
# - Large data migrations. Typically we want these to be run manually by ops so that they can
15+
# be monitored and not block the deploy for a long period of time while they run.
16+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
17+
# have ops run this and not block the deploy. Note that while adding an index is a schema
18+
# change, it's completely safe to run the operation after the code has deployed.
19+
is_dangerous = False
20+
21+
dependencies = [
22+
("sentry", "0415_backfill_actor_team_and_user"),
23+
]
24+
25+
operations = [
26+
migrations.SeparateDatabaseAndState(
27+
database_operations=[
28+
migrations.RunSQL(
29+
"""
30+
ALTER TABLE "sentry_groupsnooze" DROP COLUMN "until_escalating";
31+
""",
32+
reverse_sql="""
33+
ALTER TABLE "sentry_groupsnooze" ADD COLUMN "until_escalating" BOOLEAN DEFAULT false
34+
""",
35+
hints={"tables": ["sentry_groupsnooze"]},
36+
)
37+
],
38+
state_operations=[],
39+
)
40+
]
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Generated by Django 2.2.28 on 2023-04-07 23:43
2+
3+
from django.db import connection, migrations
4+
from psycopg2.extras import execute_values
5+
6+
from sentry.models import GroupStatus, GroupSubStatus
7+
from sentry.new_migrations.migrations import CheckedMigration
8+
from sentry.utils.query import RangeQuerySetWrapperWithProgressBar
9+
10+
BATCH_SIZE = 100
11+
12+
UPDATE_QUERY = """
13+
UPDATE sentry_groupedmessage
14+
SET substatus = data.substatus
15+
FROM (VALUES %s) as data (id, substatus)
16+
WHERE sentry_groupedmessage.id = data.id
17+
"""
18+
19+
20+
def backfill_substatus(apps, schema_editor):
21+
Group = apps.get_model("sentry", "Group")
22+
23+
queryset = RangeQuerySetWrapperWithProgressBar(
24+
Group.objects.filter(status__in=(GroupStatus.UNRESOLVED, GroupStatus.IGNORED)).values_list(
25+
"id", "status", "substatus"
26+
),
27+
result_value_getter=lambda item: item[0],
28+
)
29+
30+
cursor = connection.cursor()
31+
batch = []
32+
33+
for group_id, status, substatus in queryset:
34+
if status == GroupStatus.UNRESOLVED and substatus is None:
35+
batch.append((group_id, GroupSubStatus.ONGOING))
36+
elif status == GroupStatus.IGNORED and substatus is None:
37+
batch.append((group_id, GroupSubStatus.UNTIL_ESCALATING))
38+
39+
if len(batch) >= BATCH_SIZE:
40+
execute_values(cursor, UPDATE_QUERY, batch, page_size=BATCH_SIZE)
41+
batch = []
42+
43+
if batch:
44+
execute_values(cursor, UPDATE_QUERY, batch, page_size=BATCH_SIZE)
45+
46+
47+
class Migration(CheckedMigration):
48+
# This flag is used to mark that a migration shouldn't be automatically run in production. For
49+
# the most part, this should only be used for operations where it's safe to run the migration
50+
# after your code has deployed. So this should not be used for most operations that alter the
51+
# schema of a table.
52+
# Here are some things that make sense to mark as dangerous:
53+
# - Large data migrations. Typically we want these to be run manually by ops so that they can
54+
# be monitored and not block the deploy for a long period of time while they run.
55+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
56+
# have ops run this and not block the deploy. Note that while adding an index is a schema
57+
# change, it's completely safe to run the operation after the code has deployed.
58+
is_dangerous = True
59+
60+
dependencies = [
61+
("sentry", "0416_drop_until_escalating_in_groupsnooze"),
62+
]
63+
64+
operations = [
65+
migrations.RunPython(
66+
backfill_substatus,
67+
reverse_code=migrations.RunPython.noop,
68+
hints={"tables": ["sentry_groupedmessage"]},
69+
),
70+
]

0 commit comments

Comments
 (0)