Skip to content

Commit 8588c04

Browse files
Merge branch 'master' into priscila/feat/add-private-gaming-sdk-access-modal
2 parents 9934891 + a0f080a commit 8588c04

File tree

1,513 files changed

+18924
-15662
lines changed

Some content is hidden

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

1,513 files changed

+18924
-15662
lines changed

api-docs/paths/events/project-issues.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"get": {
33
"tags": ["Events"],
4-
"description": "Return a list of issues (groups) bound to a project. All parameters are supplied as query string parameters. \n\n A default query of ``is:unresolved`` is applied. To return results with other statuses send an new query value (i.e. ``?query=`` for all results).\n\nThe ``statsPeriod`` parameter can be used to select the timeline stats which should be present. Possible values are: ``\"\"`` (disable),``\"24h\"`` (default), ``\"14d\"``\n\nUser feedback items from the [User Feedback Widget](https://docs.sentry.io/product/user-feedback/#user-feedback-widget) are built off the issue platform, so to return a list of user feedback items for a specific project, filter for `issue.category:feedback`.",
4+
"description": "**Deprecated**: This endpoint has been replaced with the [Organization Issues endpoint](/api/events/list-an-organizations-issues/) which\nsupports filtering on project and additional functionality.\n\nReturn a list of issues (groups) bound to a project. All parameters are supplied as query string parameters. \n\n A default query of ``is:unresolved`` is applied. To return results with other statuses send an new query value (i.e. ``?query=`` for all results).\n\nThe ``statsPeriod`` parameter can be used to select the timeline stats which should be present. Possible values are: ``\"\"`` (disable),``\"24h\"`` (default), ``\"14d\"``\n\nUser feedback items from the [User Feedback Widget](https://docs.sentry.io/product/user-feedback/#user-feedback-widget) are built off the issue platform, so to return a list of user feedback items for a specific project, filter for `issue.category:feedback`.",
55
"operationId": "List a Project's Issues",
66
"parameters": [
77
{
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type {Node, Literal, Parent} from 'hast';
2+
3+
import {visit} from 'unist-util-visit';
4+
5+
/**
6+
* Remark plugin that unwraps paragraphs with only JSX elements and paragraphs inside MDX components
7+
*
8+
* - Find paragraphs that only contain MDX JSX text and/or whitespace, replace with children
9+
* - Find paragraphs that are the only children of MDX JSX elements, replace with children
10+
*
11+
*/
12+
export function remarkUnwrapMdxParagraphs() {
13+
return function (tree: Node) {
14+
// unwrap paragraphs with only JSX text and whitespace
15+
visit(tree, (node, index, parent: Parent) => {
16+
if (isParagraph(node)) {
17+
const hasOnlyJsxAndWhitespace = node.children.every(child => {
18+
switch (true) {
19+
case child.type === 'mdxJsxTextElement':
20+
return true;
21+
case isText(child):
22+
// Allow only whitespace text nodes
23+
return child.value.trim() === '';
24+
default:
25+
return false;
26+
}
27+
});
28+
if (hasOnlyJsxAndWhitespace && parent && index !== undefined) {
29+
// replace paragraph with its children
30+
parent.children.splice(index, 1, ...node.children);
31+
// return new index
32+
return index + node.children.length - 1;
33+
}
34+
}
35+
return;
36+
});
37+
// unwrap paragraphs that are only children of MDX JSX elements
38+
visit(tree, ['mdxJsxFlowElement', 'mdxJsxTextElement'], node => {
39+
if (
40+
isMdxJsxNode(node) &&
41+
node.children.length === 1 &&
42+
isParagraph(node.children[0])
43+
) {
44+
node.children = node.children[0].children;
45+
return node.children.length - 1;
46+
}
47+
return;
48+
});
49+
};
50+
}
51+
52+
function isParagraph(node?: Node): node is Parent {
53+
return node?.type === 'paragraph';
54+
}
55+
function isText(node: Node): node is Literal {
56+
return node.type === 'text';
57+
}
58+
function isMdxJsxNode(node: Node): node is Parent {
59+
return node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement';
60+
}

fixtures/backup/datetime-millis.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"key": "sentry:option-with-unzeroed-millis",
77
"last_updated": "2023-06-22T00:00:00.000Z",
88
"last_updated_by": "unknown",
9-
"value": "\"23.6.1\""
9+
"value": "23.6.1"
1010
}
1111
},
1212
{
@@ -16,7 +16,7 @@
1616
"key": "sentry:option-with-zeroed-millis",
1717
"last_updated": "2023-06-22T00:00:00Z",
1818
"last_updated_by": "unknown",
19-
"value": "\"23.6.1\""
19+
"value": "23.6.1"
2020
}
2121
}
2222
]

migrations_lockfile.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ nodestore: 0001_squashed_0002_nodestore_no_dictfield
2323

2424
notifications: 0001_move_notifications_models
2525

26-
preprod: 0012_installablepreprod
26+
preprod: 0013_binary_uuid
2727

2828
replays: 0006_add_bulk_delete_job
2929

30-
sentry: 0957_projecttemplateoption_json
30+
sentry: 0958_base_option_json_field
3131

3232
social_auth: 0003_social_auth_json_field
3333

3434
tempest: 0001_squashed_0002_make_message_type_nullable
3535

3636
uptime: 0001_squashed_0042_extra_uptime_indexes
3737

38-
workflow_engine: 0081_add_unique_constraint_to_detector_group
38+
workflow_engine: 0082_disconnect_error_detector_cron_workflows

pyproject.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ module = [
117117
"sentry.eventstore.models",
118118
"sentry.identity.gitlab.provider",
119119
"sentry.identity.oauth2",
120-
"sentry.incidents.endpoints.bases",
121120
"sentry.integrations.github.client",
122121
"sentry.integrations.gitlab.issues",
123122
"sentry.integrations.pagerduty.actions.form",
@@ -229,6 +228,7 @@ module = [
229228
"sentry.identity.github_enterprise.*",
230229
"sentry.identity.services.*",
231230
"sentry.identity.vsts_extension.*",
231+
"sentry.incidents.endpoints.bases",
232232
"sentry.incidents.utils.*",
233233
"sentry.ingest.slicing",
234234
"sentry.integrations.discord.actions.*",
@@ -424,6 +424,7 @@ module = [
424424
"sentry.utils.iterators",
425425
"sentry.utils.javascript",
426426
"sentry.utils.kafka",
427+
"sentry.utils.kafka_config",
427428
"sentry.utils.kvstore.*",
428429
"sentry.utils.lazy_service_wrapper",
429430
"sentry.utils.linksign",
@@ -463,6 +464,7 @@ module = [
463464
"sentry.workflow_engine.typings.*",
464465
"sentry.workflow_engine.utils.*",
465466
"sentry_plugins.base",
467+
"social_auth.admin",
466468
"social_auth.migrations.*",
467469
"sudo.*",
468470
"tests.sentry.api.endpoints.issues.test_organization_derive_code_mappings",
@@ -507,7 +509,7 @@ module = [
507509
"tests.sentry.issues.test_status_change_consumer",
508510
"tests.sentry.issues.test_update_inbox",
509511
"tests.sentry.middleware.test_reporting_endpoint",
510-
"tests.sentry.nodestore.bigtable.test_backend",
512+
"tests.sentry.nodestore.*",
511513
"tests.sentry.organizations.*",
512514
"tests.sentry.post_process_forwarder.*",
513515
"tests.sentry.profiling.*",

rspack.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import {TsCheckerRspackPlugin} from 'ts-checker-rspack-plugin';
2424

2525
// @ts-expect-error: ts(5097) importing `.ts` extension is required for resolution, but not enabled until `allowImportingTsExtensions` is added to tsconfig
2626
import LastBuiltPlugin from './build-utils/last-built-plugin.ts';
27+
// @ts-expect-error: ts(5097) importing `.ts` extension is required for resolution, but not enabled until `allowImportingTsExtensions` is added to tsconfig
28+
import {remarkUnwrapMdxParagraphs} from './build-utils/remark-unwrap-mdx-paragraphs.ts';
2729
import packageJson from './package.json' with {type: 'json'};
2830

2931
const {env} = process;
@@ -296,6 +298,7 @@ const appConfig: Configuration = {
296298
loader: '@mdx-js/loader',
297299
options: {
298300
remarkPlugins: [
301+
remarkUnwrapMdxParagraphs,
299302
remarkFrontmatter,
300303
remarkMdxFrontmatter,
301304
remarkGfm,
Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
from sentry import analytics
22

33

4+
@analytics.eventclass("weekly_report.sent")
45
class WeeklyReportSent(analytics.Event):
5-
type = "weekly_report.sent"
6-
7-
attributes = (
8-
analytics.Attribute("organization_id"),
9-
analytics.Attribute("user_id"),
10-
analytics.Attribute("notification_uuid"),
11-
analytics.Attribute("user_project_count", type=int),
12-
)
6+
organization_id: int
7+
user_id: int | None = None
8+
notification_uuid: str
9+
user_project_count: int
1310

1411

1512
analytics.register(WeeklyReportSent)

src/sentry/api/endpoints/project_rules.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from sentry.constants import ObjectStatus
2828
from sentry.integrations.slack.tasks.find_channel_id_for_rule import find_channel_id_for_rule
2929
from sentry.integrations.slack.utils.rule_status import RedisRuleStatus
30+
from sentry.models.project import Project
3031
from sentry.models.rule import Rule, RuleActivity, RuleActivityType
3132
from sentry.projects.project_rules.creator import ProjectRuleCreator
3233
from sentry.rules.actions import trigger_sentry_app_action_creators_for_issues
@@ -692,7 +693,7 @@ class ProjectRulesEndpoint(ProjectEndpoint):
692693
},
693694
examples=IssueAlertExamples.LIST_PROJECT_RULES,
694695
)
695-
def get(self, request: Request, project) -> Response:
696+
def get(self, request: Request, project: Project) -> Response:
696697
"""
697698
Return a list of active issue alert rules bound to a project.
698699
@@ -706,11 +707,15 @@ def get(self, request: Request, project) -> Response:
706707
status=ObjectStatus.ACTIVE,
707708
).select_related("project")
708709

710+
expand = request.GET.getlist("expand", ["lastTriggered"])
711+
709712
return self.paginate(
710713
request=request,
711714
queryset=queryset,
712715
order_by="-id",
713-
on_results=lambda x: serialize(x, request.user),
716+
on_results=lambda x: serialize(
717+
x, request.user, RuleSerializer(expand=expand, project_slug=project.slug)
718+
),
714719
)
715720

716721
@extend_schema(

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

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
from rest_framework.request import Request
1111
from rest_framework.response import Response
1212

13-
from sentry import audit_log, eventstream
13+
from sentry import audit_log, eventstream, options
1414
from sentry.api.base import audit_logger
15+
from sentry.deletions.defaults.group import GROUP_CHUNK_SIZE
1516
from sentry.deletions.tasks.groups import delete_groups as delete_groups_task
17+
from sentry.deletions.tasks.groups import delete_groups_for_project
1618
from sentry.issues.grouptype import GroupCategory
1719
from sentry.models.group import Group, GroupStatus
1820
from sentry.models.grouphash import GroupHash
@@ -47,6 +49,11 @@ def delete_group_list(
4749
# deterministic sort for sanity, and for very large deletions we'll
4850
# delete the "smaller" groups first
4951
group_list.sort(key=lambda g: (g.times_seen, g.id))
52+
53+
# Assert that all groups belong to the same project
54+
if not all(g.project_id == project.id for g in group_list):
55+
raise ValueError("All groups must belong to the same project")
56+
5057
group_ids = []
5158
error_ids = []
5259
for g in group_list:
@@ -80,8 +87,6 @@ def delete_group_list(
8087
status__in=[GroupStatus.PENDING_DELETION, GroupStatus.DELETION_IN_PROGRESS]
8188
).update(status=GroupStatus.PENDING_DELETION, substatus=None)
8289

83-
eventstream_state = eventstream.backend.start_delete_groups(project.id, group_ids)
84-
8590
# The moment groups are marked as pending deletion, we create audit entries
8691
# so that we can see who requested the deletion. Even if anything after this point
8792
# fails, we will still have a record of who requested the deletion.
@@ -95,13 +100,25 @@ def delete_group_list(
95100
# `Group` instances that are pending deletion
96101
GroupInbox.objects.filter(project_id=project.id, group__id__in=group_ids).delete()
97102

98-
delete_groups_task.apply_async(
99-
kwargs={
100-
"object_ids": group_ids,
101-
"transaction_id": str(transaction_id),
102-
"eventstream_state": eventstream_state,
103-
}
104-
)
103+
if options.get("deletions.groups.use-new-task"):
104+
# Schedule a task per GROUP_CHUNK_SIZE batch of groups
105+
for i in range(0, len(group_ids), GROUP_CHUNK_SIZE):
106+
delete_groups_for_project.apply_async(
107+
kwargs={
108+
"project_id": project.id,
109+
"object_ids": group_ids[i : i + GROUP_CHUNK_SIZE],
110+
"transaction_id": str(transaction_id),
111+
}
112+
)
113+
else:
114+
eventstream_state = eventstream.backend.start_delete_groups(project.id, group_ids)
115+
delete_groups_task.apply_async(
116+
kwargs={
117+
"object_ids": group_ids,
118+
"transaction_id": str(transaction_id),
119+
"eventstream_state": eventstream_state,
120+
}
121+
)
105122

106123

107124
def create_audit_entries(

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,9 @@ def get_attrs(self, item_list, user, **kwargs):
233233
rule_id = workflow_rule_lookup.get(wfh["workflow_id"])
234234
if rule_id:
235235
# Take the maximum date between RuleFireHistory and WorkflowFireHistory
236-
existing_date = last_triggered_lookup[rule_id]
236+
existing_date = last_triggered_lookup.get(rule_id)
237237
new_date = wfh["date_added"]
238-
if new_date > existing_date:
238+
if (existing_date and new_date > existing_date) or not existing_date:
239239
last_triggered_lookup[rule_id] = new_date
240240

241241
# Set the results

0 commit comments

Comments
 (0)