Skip to content

Commit e1ebed3

Browse files
authored
feat: add organization to prevent url paths and update related FE hooks (#95173)
This PR updates the paths for the prevent URLs to include the organization id / slug and updates the frontend hooks to pull this new URL consequently. Closes https://linear.app/getsentry/issue/CCMRG-1349/add-organization-slug-to-endpoint-path Couple postman responses, also tested locally on FE and updated the related UTs. <img width="1195" alt="Screenshot 2025-07-09 at 1 51 35 PM" src="https://github.com/user-attachments/assets/6cc4df5b-131b-472d-91fa-00afe63ebc9a" /> <img width="1203" alt="Screenshot 2025-07-09 at 11 31 10 AM" src="https://github.com/user-attachments/assets/32ae10c0-fba2-484e-b978-463664200e70" /> <!-- Sentry employees and contractors can delete or ignore the following. --> ### Legal Boilerplate Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.
1 parent b641af7 commit e1ebed3

File tree

9 files changed

+41
-29
lines changed

9 files changed

+41
-29
lines changed

src/sentry/api/urls.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,20 @@ def create_group_urls(name_prefix: str) -> list[URLPattern | URLResolver]:
10541054
),
10551055
]
10561056

1057+
PREVENT_URLS = [
1058+
re_path(
1059+
r"^owner/(?P<owner>[^/]+)/repository/(?P<repository>[^/]+)/test-results/$",
1060+
TestResultsEndpoint.as_view(),
1061+
name="sentry-api-0-test-results",
1062+
),
1063+
re_path(
1064+
r"^owner/(?P<owner>[^/]+)/repository/(?P<repository>[^/]+)/test-results-aggregates/$",
1065+
TestResultsAggregatesEndpoint.as_view(),
1066+
name="sentry-api-0-test-results-aggregates",
1067+
),
1068+
]
1069+
1070+
10571071
USER_URLS = [
10581072
re_path(
10591073
r"^$",
@@ -2395,6 +2409,10 @@ def create_group_urls(name_prefix: str) -> list[URLPattern | URLResolver]:
23952409
OrganizationInsightsTreeEndpoint.as_view(),
23962410
name="sentry-api-0-organization-insights-tree",
23972411
),
2412+
re_path(
2413+
r"^(?P<organization_id_or_slug>[^/]+)/prevent/",
2414+
include(PREVENT_URLS),
2415+
),
23982416
*workflow_urls.organization_urlpatterns,
23992417
]
24002418

@@ -3296,19 +3314,6 @@ def create_group_urls(name_prefix: str) -> list[URLPattern | URLResolver]:
32963314
*preprod_urls.preprod_internal_urlpatterns,
32973315
]
32983316

3299-
PREVENT_URLS = [
3300-
re_path(
3301-
r"^owner/(?P<owner>[^/]+)/repository/(?P<repository>[^/]+)/test-results/$",
3302-
TestResultsEndpoint.as_view(),
3303-
name="sentry-api-0-test-results",
3304-
),
3305-
re_path(
3306-
r"^owner/(?P<owner>[^/]+)/repository/(?P<repository>[^/]+)/test-results-aggregates/$",
3307-
TestResultsAggregatesEndpoint.as_view(),
3308-
name="sentry-api-0-test-results-aggregates",
3309-
),
3310-
]
3311-
33123317
urlpatterns = [
33133318
# Relay
33143319
re_path(
@@ -3374,11 +3379,6 @@ def create_group_urls(name_prefix: str) -> list[URLPattern | URLResolver]:
33743379
r"^broadcasts/",
33753380
include(BROADCAST_URLS),
33763381
),
3377-
# Prevent
3378-
re_path(
3379-
r"^prevent/",
3380-
include(PREVENT_URLS),
3381-
),
33823382
#
33833383
#
33843384
#

src/sentry/codecov/endpoints/TestResults/test_results.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from sentry.api.api_publish_status import ApiPublishStatus
88
from sentry.api.base import region_silo_endpoint
99
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST, RESPONSE_FORBIDDEN, RESPONSE_NOT_FOUND
10-
from sentry.apidocs.parameters import PreventParams
10+
from sentry.apidocs.parameters import GlobalParams, PreventParams
1111
from sentry.codecov.base import CodecovEndpoint
1212
from sentry.codecov.client import CodecovApiClient
1313
from sentry.codecov.endpoints.TestResults.query import query
@@ -29,8 +29,9 @@ def has_pagination(self, response):
2929
return True
3030

3131
@extend_schema(
32-
operation_id="Retrieve paginated list of test results for repository and owner",
32+
operation_id="Retrieve paginated list of test results for repository, owner, and organization",
3333
parameters=[
34+
GlobalParams.ORG_ID_OR_SLUG,
3435
PreventParams.OWNER,
3536
PreventParams.REPOSITORY,
3637
PreventParams.TEST_RESULTS_SORT_BY,
@@ -49,7 +50,9 @@ def has_pagination(self, response):
4950
404: RESPONSE_NOT_FOUND,
5051
},
5152
)
52-
def get(self, request: Request, owner: str, repository: str, **kwargs) -> Response:
53+
def get(
54+
self, request: Request, organization_id_or_slug: str, owner: str, repository: str, **kwargs
55+
) -> Response:
5356
"""Retrieves the list of test results for a given repository and owner. Also accepts a number of query parameters to filter the results."""
5457

5558
sort_by = request.query_params.get(

src/sentry/codecov/endpoints/TestResultsAggregates/test_results_aggregates.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from sentry.api.api_publish_status import ApiPublishStatus
77
from sentry.api.base import region_silo_endpoint
88
from sentry.apidocs.constants import RESPONSE_BAD_REQUEST, RESPONSE_FORBIDDEN, RESPONSE_NOT_FOUND
9-
from sentry.apidocs.parameters import PreventParams
9+
from sentry.apidocs.parameters import GlobalParams, PreventParams
1010
from sentry.codecov.base import CodecovEndpoint
1111
from sentry.codecov.client import CodecovApiClient
1212
from sentry.codecov.endpoints.TestResultsAggregates.query import query
@@ -27,8 +27,9 @@ class TestResultsAggregatesEndpoint(CodecovEndpoint):
2727
}
2828

2929
@extend_schema(
30-
operation_id="Retrieve aggregated test result metrics for repository and owner",
30+
operation_id="Retrieve aggregated test result metrics for repository, owner, and organization",
3131
parameters=[
32+
GlobalParams.ORG_ID_OR_SLUG,
3233
PreventParams.OWNER,
3334
PreventParams.REPOSITORY,
3435
PreventParams.INTERVAL,
@@ -41,7 +42,9 @@ class TestResultsAggregatesEndpoint(CodecovEndpoint):
4142
404: RESPONSE_NOT_FOUND,
4243
},
4344
)
44-
def get(self, request: Request, owner: str, repository: str, **kwargs) -> Response:
45+
def get(
46+
self, request: Request, organization_id_or_slug: str, owner: str, repository: str, **kwargs
47+
) -> Response:
4548
"""
4649
Retrieves aggregated test result metrics for a given repository and owner.
4750
Also accepts a query parameter to specify the time period for the metrics.

static/app/views/codecov/tests/queries/useGetTestResults.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type QueryKeyEndpointOptions,
1010
useInfiniteQuery,
1111
} from 'sentry/utils/queryClient';
12+
import useOrganization from 'sentry/utils/useOrganization';
1213
import type {
1314
SummaryFilterKey,
1415
SummaryTAFilterKey,
@@ -61,6 +62,7 @@ type QueryKey = [url: string, endpointOptions: QueryKeyEndpointOptions];
6162

6263
export function useInfiniteTestResults() {
6364
const {integratedOrg, repository, branch, codecovPeriod} = useCodecovContext();
65+
const organization = useOrganization();
6466
const [searchParams] = useSearchParams();
6567

6668
const sortBy = searchParams.get('sort') || '-commitsFailed';
@@ -79,7 +81,7 @@ export function useInfiniteTestResults() {
7981
QueryKey
8082
>({
8183
queryKey: [
82-
`/prevent/owner/${integratedOrg}/repository/${repository}/test-results/`,
84+
`/organizations/${organization.slug}/prevent/owner/${integratedOrg}/repository/${repository}/test-results/`,
8385
{query: {branch, codecovPeriod, signedSortBy, mappedFilterBy}},
8486
],
8587
queryFn: async ({

static/app/views/codecov/tests/queries/useTestResultsAggregates.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {useCodecovContext} from 'sentry/components/codecov/context/codecovContex
44
import type {QueryKeyEndpointOptions} from 'sentry/utils/queryClient';
55
import {useQuery} from 'sentry/utils/queryClient';
66
import useApi from 'sentry/utils/useApi';
7+
import useOrganization from 'sentry/utils/useOrganization';
78
import {DATE_TO_QUERY_INTERVAL} from 'sentry/views/codecov/tests/config';
89

910
type TestResultAggregate = {
@@ -27,6 +28,7 @@ type QueryKey = [url: string, endpointOptions: QueryKeyEndpointOptions];
2728

2829
export function useTestResultsAggregates() {
2930
const api = useApi();
31+
const organization = useOrganization();
3032
const {integratedOrg, repository, codecovPeriod} = useCodecovContext();
3133

3234
const {data, ...rest} = useQuery<
@@ -36,7 +38,7 @@ export function useTestResultsAggregates() {
3638
QueryKey
3739
>({
3840
queryKey: [
39-
`/prevent/owner/${integratedOrg}/repository/${repository}/test-results-aggregates/`,
41+
`/organizations/${organization.slug}/prevent/owner/${integratedOrg}/repository/${repository}/test-results-aggregates/`,
4042
{query: {codecovPeriod}},
4143
],
4244
queryFn: async ({queryKey: [url]}): Promise<TestResultAggregate> => {

static/app/views/codecov/tests/summaries/summaries.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const mockTestResultAggregates = [
2525

2626
const mockApiCall = () =>
2727
MockApiClient.addMockResponse({
28-
url: `/prevent/owner/some-org-name/repository/some-repository/test-results-aggregates/`,
28+
url: `/organizations/org-slug/prevent/owner/some-org-name/repository/some-repository/test-results-aggregates/`,
2929
method: 'GET',
3030
body: {
3131
results: mockTestResultAggregates,

static/app/views/codecov/tests/tests.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const mockTestResultAggregates = [
4141

4242
const mockApiCall = () => {
4343
MockApiClient.addMockResponse({
44-
url: `/prevent/owner/some-org-name/repository/some-repository/test-results/`,
44+
url: `/organizations/org-slug/prevent/owner/some-org-name/repository/some-repository/test-results/`,
4545
method: 'GET',
4646
body: {
4747
results: mockTestResultsData,
@@ -54,7 +54,7 @@ const mockApiCall = () => {
5454
});
5555

5656
MockApiClient.addMockResponse({
57-
url: `/prevent/owner/some-org-name/repository/some-repository/test-results-aggregates/`,
57+
url: `/organizations/org-slug/prevent/owner/some-org-name/repository/some-repository/test-results-aggregates/`,
5858
method: 'GET',
5959
body: {
6060
results: mockTestResultAggregates,

tests/sentry/codecov/endpoints/test_test_result_aggregates.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def reverse_url(self, owner="testowner", repository="testrepo"):
1717
return reverse(
1818
self.endpoint_name,
1919
kwargs={
20+
"organization_id_or_slug": self.organization.slug,
2021
"owner": owner,
2122
"repository": repository,
2223
},

tests/sentry/codecov/endpoints/test_test_results.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def reverse_url(self, owner="testowner", repository="testrepo"):
2020
return reverse(
2121
self.endpoint,
2222
kwargs={
23+
"organization_id_or_slug": self.organization.slug,
2324
"owner": owner,
2425
"repository": repository,
2526
},

0 commit comments

Comments
 (0)