Skip to content

Commit a710b6f

Browse files
authored
fix(aci): Fix casing for open periods query params (#98315)
- Fixes casing for query params on open periods endpoint (`detectorId` vs `detector_id`) - Adds doc decorators
1 parent 2c6514c commit a710b6f

File tree

2 files changed

+57
-15
lines changed

2 files changed

+57
-15
lines changed

src/sentry/workflow_engine/endpoints/organization_open_periods.py

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Any
44

5+
from drf_spectacular.utils import OpenApiParameter, extend_schema
56
from rest_framework.exceptions import ParseError, ValidationError
67
from rest_framework.request import Request
78
from rest_framework.response import Response
@@ -12,6 +13,14 @@
1213
from sentry.api.bases import OrganizationDetectorPermission, OrganizationEndpoint
1314
from sentry.api.paginator import GenericOffsetPaginator
1415
from sentry.api.utils import get_date_range_from_params
16+
from sentry.apidocs.constants import (
17+
RESPONSE_BAD_REQUEST,
18+
RESPONSE_FORBIDDEN,
19+
RESPONSE_NOT_FOUND,
20+
RESPONSE_UNAUTHORIZED,
21+
)
22+
from sentry.apidocs.parameters import CursorQueryParam, GlobalParams, VisibilityParams
23+
from sentry.apidocs.utils import inline_sentry_response_serializer
1524
from sentry.exceptions import InvalidParams
1625
from sentry.models.group import Group
1726
from sentry.models.groupopenperiod import OpenPeriod, get_open_periods_for_group
@@ -21,6 +30,7 @@
2130

2231

2332
@region_silo_endpoint
33+
@extend_schema(tags=["Workflows"])
2434
class OrganizationOpenPeriodsEndpoint(OrganizationEndpoint):
2535
publish_status = {
2636
"GET": ApiPublishStatus.PRIVATE,
@@ -35,10 +45,10 @@ def get_group_from_detector_id(
3545
try:
3646
detector = Detector.objects.select_related("project").get(id=detector_id)
3747
except (Detector.DoesNotExist, ValueError):
38-
raise ValidationError({"detector_id": "Detector not found"})
48+
raise ValidationError({"detectorId": "Detector not found"})
3949

4050
if detector.project.organization_id != organization.id:
41-
raise ValidationError({"detector_id": "Detector not found"})
51+
raise ValidationError({"detectorId": "Detector not found"})
4252

4353
detector_group = (
4454
DetectorGroup.objects.filter(detector=detector).order_by("-date_added").first()
@@ -50,13 +60,45 @@ def get_group_from_group_id(self, group_id: str, organization: Organization) ->
5060
try:
5161
group = Group.objects.select_related("project").get(id=group_id)
5262
except (Group.DoesNotExist, ValueError):
53-
raise ValidationError({"group_id": "Group not found"})
63+
raise ValidationError({"groupId": "Group not found"})
5464

5565
if group.project.organization_id != organization.id:
56-
raise ValidationError({"group_id": "Group not found"})
66+
raise ValidationError({"groupId": "Group not found"})
5767

5868
return group
5969

70+
@extend_schema(
71+
operation_id="Fetch Group Open Periods",
72+
parameters=[
73+
GlobalParams.ORG_ID_OR_SLUG,
74+
GlobalParams.START,
75+
GlobalParams.END,
76+
GlobalParams.STATS_PERIOD,
77+
VisibilityParams.PER_PAGE,
78+
CursorQueryParam,
79+
OpenApiParameter(
80+
name="detectorId",
81+
location="query",
82+
required=False,
83+
type=str,
84+
description="ID of the detector which is associated with the issue group.",
85+
),
86+
OpenApiParameter(
87+
name="groupId",
88+
location="query",
89+
required=False,
90+
type=str,
91+
description="ID of the issue group.",
92+
),
93+
],
94+
responses={
95+
200: inline_sentry_response_serializer("ListOpenPeriods", list[OpenPeriod]),
96+
400: RESPONSE_BAD_REQUEST,
97+
401: RESPONSE_UNAUTHORIZED,
98+
403: RESPONSE_FORBIDDEN,
99+
404: RESPONSE_NOT_FOUND,
100+
},
101+
)
60102
def get(self, request: Request, organization: Organization) -> Response:
61103
"""
62104
Return a list of open periods for a group, identified by either detector_id or group_id.
@@ -66,13 +108,13 @@ def get(self, request: Request, organization: Organization) -> Response:
66108
except InvalidParams:
67109
raise ParseError(detail="Invalid date range")
68110

69-
detector_id_param = request.GET.get("detector_id")
70-
group_id_param = request.GET.get("group_id")
111+
detector_id_param = request.GET.get("detectorId")
112+
group_id_param = request.GET.get("groupId")
71113

72114
if not detector_id_param and not group_id_param:
73-
raise ValidationError({"detail": "Must provide either detector_id or group_id"})
115+
raise ValidationError({"detail": "Must provide either detectorId or groupId"})
74116
if detector_id_param and group_id_param:
75-
raise ValidationError({"detail": "Must provide only one of detector_id or group_id"})
117+
raise ValidationError({"detail": "Must provide only one of detectorId or groupId"})
76118

77119
target_group: Group | None = (
78120
self.get_group_from_detector_id(detector_id_param, organization)

tests/sentry/workflow_engine/endpoints/test_organization_open_periods.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ def test_no_group_link(self) -> None:
3737
# Create a new detector with no linked group
3838
detector = self.create_detector()
3939
resp = self.get_success_response(
40-
self.organization.slug, qs_params={"detector_id": detector.id}
40+
self.organization.slug, qs_params={"detectorId": detector.id}
4141
)
4242
assert resp.data == []
4343

4444
@with_feature("organizations:issue-open-periods")
4545
def test_open_period_linked_to_group(self) -> None:
4646
response = self.get_success_response(
47-
*self.get_url_args(), qs_params={"detector_id": self.detector.id}
47+
*self.get_url_args(), qs_params={"detectorId": self.detector.id}
4848
)
4949
assert len(response.data) == 1
5050
open_period = response.data[0]
@@ -56,7 +56,7 @@ def test_open_period_linked_to_group(self) -> None:
5656
@with_feature("organizations:issue-open-periods")
5757
def test_open_periods_group_id(self) -> None:
5858
response = self.get_success_response(
59-
*self.get_url_args(), qs_params={"group_id": self.group.id}
59+
*self.get_url_args(), qs_params={"groupId": self.group.id}
6060
)
6161
assert len(response.data) == 1
6262

@@ -73,7 +73,7 @@ def test_open_periods_new_group_with_last_checked(self) -> None:
7373
last_checked = timezone.now() - timedelta(seconds=alert_rule.snuba_query.time_window)
7474

7575
response = self.get_success_response(
76-
*self.get_url_args(), qs_params={"group_id": self.group.id}
76+
*self.get_url_args(), qs_params={"groupId": self.group.id}
7777
)
7878
assert response.status_code == 200, response.content
7979
assert len(response.data) == 1
@@ -97,7 +97,7 @@ def test_open_periods_resolved_group(self) -> None:
9797
)
9898

9999
response = self.get_success_response(
100-
*self.get_url_args(), qs_params={"group_id": self.group.id}
100+
*self.get_url_args(), qs_params={"groupId": self.group.id}
101101
)
102102
assert response.status_code == 200, response.content
103103
assert response.data == [
@@ -143,7 +143,7 @@ def test_open_periods_unresolved_group(self) -> None:
143143
)
144144

145145
response = self.get_success_response(
146-
*self.get_url_args(), qs_params={"group_id": self.group.id}
146+
*self.get_url_args(), qs_params={"groupId": self.group.id}
147147
)
148148
assert response.status_code == 200, response.content
149149
assert response.data == [
@@ -196,7 +196,7 @@ def test_open_periods_limit(self) -> None:
196196
)
197197

198198
response = self.get_success_response(
199-
*self.get_url_args(), qs_params={"group_id": self.group.id, "per_page": 1}
199+
*self.get_url_args(), qs_params={"groupId": self.group.id, "per_page": 1}
200200
)
201201
assert response.status_code == 200, response.content
202202
assert len(response.data) == 1

0 commit comments

Comments
 (0)