diff --git a/src/sentry/api/endpoints/organization_trace_item_attributes.py b/src/sentry/api/endpoints/organization_trace_item_attributes.py
index c46894bd2de607..0839655d21d084 100644
--- a/src/sentry/api/endpoints/organization_trace_item_attributes.py
+++ b/src/sentry/api/endpoints/organization_trace_item_attributes.py
@@ -141,7 +141,6 @@ class OrganizationTraceItemAttributesEndpointBase(OrganizationEventsEndpointBase
"organizations:ourlogs-enabled",
"organizations:visibility-explore-view",
"organizations:tracemetrics-enabled",
- "organizations:preprod-frontend-routes",
]
def has_feature(self, organization: Organization, request: Request) -> bool:
diff --git a/src/sentry/features/temporary.py b/src/sentry/features/temporary.py
index fe2aac3767b0b8..e9c2abc4afa3e1 100644
--- a/src/sentry/features/temporary.py
+++ b/src/sentry/features/temporary.py
@@ -243,8 +243,6 @@ def register_temporary_features(manager: FeatureManager) -> None:
manager.add("organizations:performance-web-vitals-seer-suggestions", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable the warning banner to inform users of pending deprecation of the transactions dataset
manager.add("organizations:performance-transaction-deprecation-banner", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
- # Enable preprod frontend routes
- manager.add("organizations:preprod-frontend-routes", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable preprod_artifact webhook subscription UI in Sentry App settings
manager.add("organizations:preprod-artifact-webhooks", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=True)
# Enable preprod issue reporting
diff --git a/src/sentry/preprod/api/endpoints/builds.py b/src/sentry/preprod/api/endpoints/builds.py
index 8bb20e598ed62f..f6a919d39ce8b1 100644
--- a/src/sentry/preprod/api/endpoints/builds.py
+++ b/src/sentry/preprod/api/endpoints/builds.py
@@ -4,7 +4,6 @@
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import features
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -21,8 +20,6 @@
logger = logging.getLogger(__name__)
-ERR_FEATURE_REQUIRED = "Feature {} is not enabled for the organization."
-
@cell_silo_endpoint
class BuildsEndpoint(OrganizationEndpoint):
@@ -32,14 +29,6 @@ class BuildsEndpoint(OrganizationEndpoint):
}
def get(self, request: Request, organization: Organization) -> Response:
- if not features.has(
- "organizations:preprod-frontend-routes", organization, actor=request.user
- ):
- return Response(
- {"detail": ERR_FEATURE_REQUIRED.format("organizations:preprod-frontend-routes")},
- status=403,
- )
-
def on_results(artifacts: list[PreprodArtifact]) -> list[dict[str, Any]]:
results = []
for artifact in artifacts:
diff --git a/src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py b/src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
index 13305efab8b9b1..821e77f9fd6f12 100644
--- a/src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
+++ b/src/sentry/preprod/api/endpoints/organization_preprod_artifact_assemble.py
@@ -5,11 +5,10 @@
import jsonschema
import orjson
import sentry_sdk
-from django.conf import settings
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import analytics, features
+from sentry import analytics
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -145,11 +144,6 @@ def post(self, request: Request, project: Project) -> Response:
)
)
- if not settings.IS_DEV and not features.has(
- "organizations:preprod-frontend-routes", project.organization, actor=request.user
- ):
- return Response({"error": "Feature not enabled"}, status=403)
-
with sentry_sdk.start_span(op="preprod_artifact.assemble"):
data, error_message = validate_preprod_artifact_schema(request.body)
if error_message:
diff --git a/src/sentry/preprod/api/endpoints/project_preprod_artifact_delete.py b/src/sentry/preprod/api/endpoints/project_preprod_artifact_delete.py
index add3d2d99e4bd9..3f070712ca495f 100644
--- a/src/sentry/preprod/api/endpoints/project_preprod_artifact_delete.py
+++ b/src/sentry/preprod/api/endpoints/project_preprod_artifact_delete.py
@@ -5,7 +5,7 @@
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import analytics, features
+from sentry import analytics
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -34,11 +34,6 @@ def delete(
) -> Response:
"""Delete a preprod artifact and all associated data"""
- if not features.has(
- "organizations:preprod-frontend-routes", project.organization, actor=request.user
- ):
- return Response({"error": "Feature not enabled"}, status=403)
-
analytics.record(
PreprodArtifactApiDeleteEvent(
organization_id=project.organization_id,
diff --git a/src/sentry/preprod/api/endpoints/project_preprod_build_details.py b/src/sentry/preprod/api/endpoints/project_preprod_build_details.py
index 8a9e3d5e83de91..5bc3e0261afea2 100644
--- a/src/sentry/preprod/api/endpoints/project_preprod_build_details.py
+++ b/src/sentry/preprod/api/endpoints/project_preprod_build_details.py
@@ -5,7 +5,7 @@
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import analytics, features
+from sentry import analytics
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -58,11 +58,6 @@ def get(
)
)
- if not features.has(
- "organizations:preprod-frontend-routes", project.organization, actor=request.user
- ):
- return Response({"error": "Feature not enabled"}, status=403)
-
cutoff = get_size_retention_cutoff(project.organization)
if head_artifact.date_added < cutoff:
return Response({"detail": "This build's size data has expired."}, status=404)
diff --git a/src/sentry/preprod/api/endpoints/public/organization_preprod_artifact_install_details.py b/src/sentry/preprod/api/endpoints/public/organization_preprod_artifact_install_details.py
index a385f0ac8e43a5..dd7381f3146943 100644
--- a/src/sentry/preprod/api/endpoints/public/organization_preprod_artifact_install_details.py
+++ b/src/sentry/preprod/api/endpoints/public/organization_preprod_artifact_install_details.py
@@ -4,7 +4,6 @@
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import features
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -72,11 +71,6 @@ def get(
and iOS-specific code signing information.
"""
- if not features.has(
- "organizations:preprod-frontend-routes", organization, actor=request.user
- ):
- return Response({"detail": "Feature not enabled"}, status=403)
-
try:
artifact = PreprodArtifact.objects.select_related(
"mobile_app_info",
diff --git a/src/sentry/preprod/api/endpoints/public/organization_preprod_size_analysis.py b/src/sentry/preprod/api/endpoints/public/organization_preprod_size_analysis.py
index 3d4f8028aff1f8..40b25c88af2c44 100644
--- a/src/sentry/preprod/api/endpoints/public/organization_preprod_size_analysis.py
+++ b/src/sentry/preprod/api/endpoints/public/organization_preprod_size_analysis.py
@@ -8,7 +8,6 @@
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import features
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -119,11 +118,6 @@ def get(
- `COMPLETED`: Analysis finished successfully with full size data.
"""
- if not features.has(
- "organizations:preprod-frontend-routes", organization, actor=request.user
- ):
- return Response({"detail": "Feature not enabled"}, status=403)
-
try:
head_artifact = PreprodArtifact.objects.select_related(
"mobile_app_info", "build_configuration", "commit_comparison"
diff --git a/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare.py b/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare.py
index b845451f8bd380..09e9b56a88c3da 100644
--- a/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare.py
+++ b/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare.py
@@ -7,7 +7,7 @@
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import analytics, features
+from sentry import analytics
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -113,11 +113,6 @@ def get(
)
)
- if not features.has(
- "organizations:preprod-frontend-routes", project.organization, actor=request.user
- ):
- return Response({"detail": "Feature not enabled"}, status=403)
-
cutoff = get_size_retention_cutoff(project.organization)
if head_artifact.date_added < cutoff or base_artifact.date_added < cutoff:
return Response({"detail": "This build's size data has expired."}, status=404)
@@ -279,11 +274,6 @@ def post(
)
)
- if not features.has(
- "organizations:preprod-frontend-routes", project.organization, actor=request.user
- ):
- return Response({"detail": "Feature not enabled"}, status=403)
-
cutoff = get_size_retention_cutoff(project.organization)
if head_artifact.date_added < cutoff or base_artifact.date_added < cutoff:
return Response({"detail": "This build's size data has expired."}, status=404)
diff --git a/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare_download.py b/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare_download.py
index 1ffd7c7b9f47cc..0bfae994a7719d 100644
--- a/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare_download.py
+++ b/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_compare_download.py
@@ -6,7 +6,7 @@
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import analytics, features
+from sentry import analytics
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -55,11 +55,6 @@ def get(
)
)
- if not features.has(
- "organizations:preprod-frontend-routes", project.organization, actor=request.user
- ):
- return Response({"detail": "Feature not enabled"}, status=403)
-
logger.info(
"preprod.size_analysis.compare.api.download",
extra={
diff --git a/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_download.py b/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_download.py
index c3fab44caf1076..b8fa4acc721772 100644
--- a/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_download.py
+++ b/src/sentry/preprod/api/endpoints/size_analysis/project_preprod_size_analysis_download.py
@@ -1,11 +1,10 @@
from __future__ import annotations
-from django.conf import settings
from django.http.response import HttpResponseBase
from rest_framework.request import Request
from rest_framework.response import Response
-from sentry import analytics, features
+from sentry import analytics
from sentry.api.api_owners import ApiOwner
from sentry.api.api_publish_status import ApiPublishStatus
from sentry.api.base import cell_silo_endpoint
@@ -58,11 +57,6 @@ def get(
)
)
- if not settings.IS_DEV and not features.has(
- "organizations:preprod-frontend-routes", project.organization, actor=request.user
- ):
- return Response({"detail": "Feature not enabled"}, status=403)
-
cutoff = get_size_retention_cutoff(project.organization)
if head_artifact.date_added < cutoff:
return Response({"detail": "This build's size data has expired."}, status=404)
diff --git a/static/app/views/preprod/buildDetails/header/buildDetailsHeaderContent.tsx b/static/app/views/preprod/buildDetails/header/buildDetailsHeaderContent.tsx
index c5cf3793e548aa..017f03f976e419 100644
--- a/static/app/views/preprod/buildDetails/header/buildDetailsHeaderContent.tsx
+++ b/static/app/views/preprod/buildDetails/header/buildDetailsHeaderContent.tsx
@@ -5,7 +5,6 @@ import {Button, LinkButton} from '@sentry/scraps/button';
import {Flex} from '@sentry/scraps/layout';
import {Text} from '@sentry/scraps/text';
-import Feature from 'sentry/components/acl/feature';
import {Breadcrumbs, type Crumb} from 'sentry/components/breadcrumbs';
import {ConfirmDelete} from 'sentry/components/confirmDelete';
import {DropdownButton} from 'sentry/components/dropdownButton';
@@ -198,15 +197,13 @@ export function BuildDetailsHeaderContent(props: BuildDetailsHeaderContentProps)
>
{t('Compare Build')}
-
- {project && (
- }
- aria-label={t('Settings')}
- to={`/settings/${organization.slug}/projects/${project.slug}/mobile-builds/`}
- />
- )}
-
+ {project && (
+ }
+ aria-label={t('Settings')}
+ to={`/settings/${organization.slug}/projects/${project.slug}/mobile-builds/`}
+ />
+ )}
{t('Compare Build')}
-
- {project && (
- }
- aria-label={t('Settings')}
- to={`/settings/${organization.slug}/projects/${project.slug}/mobile-builds/`}
- />
- )}
-
+ {project && (
+ }
+ aria-label={t('Settings')}
+ to={`/settings/${organization.slug}/projects/${project.slug}/mobile-builds/`}
+ />
+ )}
(
-
-
-
- {t("You don't have access to this feature")}
-
-
-
- )}
- >
-
-
-
-
+
+
+
);
}
diff --git a/static/app/views/releases/detail/header/releaseHeader.tsx b/static/app/views/releases/detail/header/releaseHeader.tsx
index c1ab3a6b647be9..4852dbf8158b68 100644
--- a/static/app/views/releases/detail/header/releaseHeader.tsx
+++ b/static/app/views/releases/detail/header/releaseHeader.tsx
@@ -103,10 +103,7 @@ export function ReleaseHeader({
to: 'builds/',
};
- if (
- organization.features?.includes('preprod-frontend-routes') &&
- (numberOfMobileBuilds || isMobileRelease(project.platform, false))
- ) {
+ if (numberOfMobileBuilds || isMobileRelease(project.platform, false)) {
tabs.push(buildsTab);
}
diff --git a/static/app/views/releases/list/index.spec.tsx b/static/app/views/releases/list/index.spec.tsx
index 4f22a46eb4f3df..37874f430225ec 100644
--- a/static/app/views/releases/list/index.spec.tsx
+++ b/static/app/views/releases/list/index.spec.tsx
@@ -21,7 +21,7 @@ import {ReleasesStatusOption} from 'sentry/views/releases/list/releasesStatusOpt
describe('ReleasesList', () => {
const organization = OrganizationFixture({
- features: ['preprod-frontend-routes'],
+ features: [],
});
const projects = [ProjectFixture({features: ['releases']})];
const semverVersionInfo = {
diff --git a/static/app/views/releases/list/index.tsx b/static/app/views/releases/list/index.tsx
index 5978ad7ff89478..fd89ee0626c112 100644
--- a/static/app/views/releases/list/index.tsx
+++ b/static/app/views/releases/list/index.tsx
@@ -244,7 +244,6 @@ export default function ReleasesList() {
: selectedIds.map(id => `${id}`);
}, [selection.projects]);
- const hasPreprodFeature = organization.features?.includes('preprod-frontend-routes');
const hasSnapshotsFeature = organization.features?.includes('preprod-snapshots');
const {statsPeriod, start, end, utc} = normalizeDateTimeParams(location.query);
@@ -261,12 +260,9 @@ export default function ReleasesList() {
},
}),
staleTime: 60_000,
- enabled: !!hasPreprodFeature,
placeholderData: keepPreviousData,
});
- // When "All Projects" is selected (represented by [-1]), check all accessible projects
- // When specific projects are selected, check only those projects
const hasAnyStrictlyMobileProject = useMemo(() => {
const isAllProjects =
selectedProjectIds.length === 1 &&
@@ -275,7 +271,6 @@ export default function ReleasesList() {
? projects.map(p => p.id)
: selectedProjectIds;
- // Check if at least one project has a mobile platform
return projectIdsToCheck
.map(id => ProjectsStore.getById(id))
.filter(Boolean)
@@ -285,8 +280,7 @@ export default function ReleasesList() {
const hasBuildsData =
!buildsProbeQuery.isPending && (buildsProbeQuery.data?.length ?? 0) > 0;
- const shouldShowMobileBuildsTab =
- hasPreprodFeature && (hasBuildsData || hasAnyStrictlyMobileProject);
+ const shouldShowMobileBuildsTab = hasBuildsData || hasAnyStrictlyMobileProject;
const shouldShowSnapshotsTab = !!hasSnapshotsFeature;
const shouldShowPreprodTabs = shouldShowMobileBuildsTab || shouldShowSnapshotsTab;
@@ -509,7 +503,11 @@ export default function ReleasesList() {
key="releases"
to={{
pathname: location.pathname,
- query: {...location.query, query: undefined, tab: undefined},
+ query: {
+ ...location.query,
+ query: undefined,
+ tab: undefined,
+ },
}}
textValue={t('Releases')}
>
@@ -654,7 +652,9 @@ export default function ReleasesList() {
);
}
-const ReleasesPageFilterBar = styled(PageFilterBar)<{shouldShowPreprodTabs: boolean}>`
+const ReleasesPageFilterBar = styled(PageFilterBar)<{
+ shouldShowPreprodTabs: boolean;
+}>`
${p => !p.shouldShowPreprodTabs && `margin-bottom: ${p.theme.space.xl};`}
`;
diff --git a/static/app/views/settings/project/navigationConfiguration.tsx b/static/app/views/settings/project/navigationConfiguration.tsx
index 9d0ea6de594e0a..5e38c7baf81cd1 100644
--- a/static/app/views/settings/project/navigationConfiguration.tsx
+++ b/static/app/views/settings/project/navigationConfiguration.tsx
@@ -131,7 +131,6 @@ export function getNavigationConfiguration({
{
path: `${pathPrefix}/mobile-builds/`,
title: t('Mobile Builds'),
- show: () => !!organization?.features?.includes('preprod-frontend-routes'),
badge: () => 'new',
description: t('Size analysis and build distribution configuration.'),
},
diff --git a/static/app/views/settings/project/preprod/index.tsx b/static/app/views/settings/project/preprod/index.tsx
index 2345e1c8a9fd5a..6b4b3c3a931a87 100644
--- a/static/app/views/settings/project/preprod/index.tsx
+++ b/static/app/views/settings/project/preprod/index.tsx
@@ -58,7 +58,7 @@ export default function PreprodSettings() {
};
return (
-
+
)}
-
+
);
}
diff --git a/tests/sentry/preprod/api/bases/test_preprod_artifact_endpoint.py b/tests/sentry/preprod/api/bases/test_preprod_artifact_endpoint.py
index 4b6007ea017b65..d0971c2c67ab73 100644
--- a/tests/sentry/preprod/api/bases/test_preprod_artifact_endpoint.py
+++ b/tests/sentry/preprod/api/bases/test_preprod_artifact_endpoint.py
@@ -1,6 +1,5 @@
from sentry.constants import ObjectStatus
from sentry.testutils.cases import APITestCase
-from sentry.testutils.helpers.features import with_feature
class PreprodArtifactEndpointTest(APITestCase):
@@ -12,7 +11,6 @@ def setUp(self) -> None:
def _get_url(self, org_slug, artifact_id):
return f"/api/0/organizations/{org_slug}/preprodartifacts/{artifact_id}/build-details/"
- @with_feature("organizations:preprod-frontend-routes")
def test_extracts_project_from_artifact(self) -> None:
url = self._get_url(self.organization.slug, self.artifact.id)
response = self.client.get(url)
diff --git a/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_artifact_install_details.py b/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_artifact_install_details.py
index 633a9c63a1bc97..19f63c8f0b3231 100644
--- a/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_artifact_install_details.py
+++ b/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_artifact_install_details.py
@@ -27,13 +27,6 @@ def setUp(self) -> None:
build_number=42,
)
- self.feature_context = self.feature({"organizations:preprod-frontend-routes": True})
- self.feature_context.__enter__()
-
- def tearDown(self):
- self.feature_context.__exit__(None, None, None)
- super().tearDown()
-
def _get_url(self, artifact_id=None):
artifact_id = artifact_id or self.preprod_artifact.id
return reverse(
@@ -41,12 +34,6 @@ def _get_url(self, artifact_id=None):
args=[self.organization.slug, artifact_id],
)
- def test_feature_flag_disabled(self) -> None:
- with self.feature({"organizations:preprod-frontend-routes": False}):
- response = self.client.get(self._get_url())
- assert response.status_code == 403
- assert response.json()["detail"] == "Feature not enabled"
-
def test_artifact_not_found(self) -> None:
response = self.client.get(self._get_url(artifact_id=999999))
assert response.status_code == 404
diff --git a/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_size_analysis.py b/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_size_analysis.py
index 2c3dba12951162..7169c17d1c2168 100644
--- a/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_size_analysis.py
+++ b/tests/sentry/preprod/api/endpoints/public/test_organization_preprod_size_analysis.py
@@ -34,13 +34,6 @@ def setUp(self) -> None:
build_number=42,
)
- self.feature_context = self.feature({"organizations:preprod-frontend-routes": True})
- self.feature_context.__enter__()
-
- def tearDown(self):
- self.feature_context.__exit__(None, None, None)
- super().tearDown()
-
def _get_url(self, artifact_id=None):
artifact_id = artifact_id or self.preprod_artifact.id
return reverse(
@@ -67,12 +60,6 @@ def _make_analysis_data(self, **overrides):
defaults.update(overrides)
return defaults
- def test_feature_flag_disabled(self) -> None:
- with self.feature({"organizations:preprod-frontend-routes": False}):
- response = self.client.get(self._get_url())
- assert response.status_code == 403
- assert response.json()["detail"] == "Feature not enabled"
-
def test_artifact_not_found(self) -> None:
response = self.client.get(self._get_url(artifact_id=999999))
assert response.status_code == 404
diff --git a/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare.py b/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare.py
index 08e84a5419ec70..df05202d76185e 100644
--- a/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare.py
+++ b/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare.py
@@ -1,7 +1,6 @@
from datetime import timedelta
from unittest.mock import patch
-from django.test import override_settings
from django.urls import reverse
from django.utils import timezone
@@ -85,7 +84,6 @@ def _get_url(self, head_artifact_id=None, base_artifact_id=None):
args=[self.organization.slug, head_artifact_id, base_artifact_id],
)
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_success_with_completed_comparison(self) -> None:
"""Test GET endpoint returns successful comparison when comparison exists and is completed"""
# Create a successful comparison
@@ -121,7 +119,6 @@ def test_get_comparison_success_with_completed_comparison(self) -> None:
assert comparison_data["error_code"] is None
assert comparison_data["error_message"] is None
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_success_with_failed_comparison(self) -> None:
"""Test GET endpoint returns failed comparison when comparison exists and failed"""
# Create a failed comparison
@@ -146,7 +143,6 @@ def test_get_comparison_success_with_failed_comparison(self) -> None:
assert comparison_data["error_code"] == str(PreprodArtifactSizeComparison.ErrorCode.UNKNOWN)
assert comparison_data["error_message"] == "Comparison failed due to processing error"
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_success_with_pending_comparison(self) -> None:
"""Test GET endpoint returns processing state for pending comparison"""
# Create a pending comparison (which should be shown as PROCESSING to frontend)
@@ -170,7 +166,6 @@ def test_get_comparison_success_with_pending_comparison(self) -> None:
assert comparison_data["error_code"] is None
assert comparison_data["error_message"] is None
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_success_with_processing_comparison(self) -> None:
"""Test GET endpoint returns processing comparison when comparison is in progress"""
# Create a processing comparison
@@ -193,7 +188,6 @@ def test_get_comparison_success_with_processing_comparison(self) -> None:
assert comparison_data["error_code"] is None
assert comparison_data["error_message"] is None
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_success_with_no_comparison(self) -> None:
"""Test GET endpoint returns no comparison when no comparison exists yet"""
response = self.get_success_response(
@@ -204,7 +198,6 @@ def test_get_comparison_success_with_no_comparison(self) -> None:
data = response.data
assert len(data["comparisons"]) == 0
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_success_with_no_matching_base_metric(self) -> None:
"""Test GET endpoint handles case where no matching base metric exists"""
self.create_preprod_artifact_size_comparison(
@@ -243,7 +236,6 @@ def test_get_comparison_success_with_no_matching_base_metric(self) -> None:
assert watch_comparison["error_code"] == "NO_BASE_METRIC"
assert watch_comparison["error_message"] == "No matching base artifact size metric found."
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_head_artifact_not_found(self) -> None:
"""Test GET endpoint returns 404 when head artifact doesn't exist"""
response = self.get_error_response(
@@ -254,7 +246,6 @@ def test_get_comparison_head_artifact_not_found(self) -> None:
)
assert "The requested head preprod artifact does not exist" in response.data["detail"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_base_artifact_not_found(self) -> None:
"""Test GET endpoint returns 404 when base artifact doesn't exist"""
response = self.get_error_response(
@@ -265,7 +256,6 @@ def test_get_comparison_base_artifact_not_found(self) -> None:
)
assert "The requested base preprod artifact does not exist" in response.data["detail"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_artifacts_different_projects(self) -> None:
"""Test GET endpoint returns 404 when head and base artifacts belong to different projects"""
other_project = self.create_project(organization=self.organization)
@@ -285,7 +275,6 @@ def test_get_comparison_artifacts_different_projects(self) -> None:
)
assert response.data["detail"] == "The requested base preprod artifact does not exist"
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_base_artifact_wrong_project(self) -> None:
"""Test GET endpoint returns 404 when base artifact belongs to different project"""
other_project = self.create_project(organization=self.organization)
@@ -305,7 +294,6 @@ def test_get_comparison_base_artifact_wrong_project(self) -> None:
)
assert response.data["detail"] == "The requested base preprod artifact does not exist"
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_head_artifact_no_size_metrics(self) -> None:
"""Test GET endpoint returns 404 when head artifact has no size metrics"""
# Create artifact without size metrics
@@ -328,7 +316,6 @@ def test_get_comparison_head_artifact_no_size_metrics(self) -> None:
in response.data["detail"]
)
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_base_artifact_no_size_metrics(self) -> None:
"""Test GET endpoint returns 404 when base artifact has no size metrics"""
# Create artifact without size metrics
@@ -351,18 +338,6 @@ def test_get_comparison_base_artifact_no_size_metrics(self) -> None:
in response.data["detail"]
)
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": False})
- def test_get_comparison_feature_disabled(self) -> None:
- """Test GET endpoint returns 403 when feature flag is disabled"""
- response = self.get_error_response(
- self.organization.slug,
- self.head_artifact.id,
- self.base_artifact.id,
- status_code=403,
- )
- assert response.data["detail"] == "Feature not enabled"
-
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_get_comparison_multiple_metrics(self) -> None:
"""Test GET endpoint handles multiple size metrics correctly"""
self.create_preprod_artifact_size_comparison(
@@ -425,7 +400,6 @@ def test_get_comparison_multiple_metrics(self) -> None:
assert watch_comparison_data["base_size_metric_id"] == base_watch_metric.id
assert watch_comparison_data["comparison_id"] == watch_comparison.id
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
@patch("sentry.preprod.size_analysis.tasks.manual_size_analysis_comparison.apply_async")
def test_post_comparison_success(self, mock_apply_async):
"""Test POST endpoint successfully triggers comparison and creates PENDING records"""
@@ -467,7 +441,6 @@ def test_post_comparison_success(self, mock_apply_async):
assert comparison.state == PreprodArtifactSizeComparison.State.PENDING
assert comparison.organization_id == self.organization.id
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_head_artifact_not_found(self) -> None:
"""Test POST endpoint returns 404 when head artifact doesn't exist"""
response = self.get_error_response(
@@ -479,7 +452,6 @@ def test_post_comparison_head_artifact_not_found(self) -> None:
)
assert "The requested head preprod artifact does not exist" in response.data["detail"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_base_artifact_not_found(self) -> None:
"""Test POST endpoint returns 404 when base artifact doesn't exist"""
response = self.get_error_response(
@@ -491,7 +463,6 @@ def test_post_comparison_base_artifact_not_found(self) -> None:
)
assert "The requested base preprod artifact does not exist" in response.data["detail"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_head_artifact_no_size_metrics(self) -> None:
"""Test POST endpoint returns 404 when head artifact has no size metrics"""
artifact_no_metrics = self.create_preprod_artifact(
@@ -510,7 +481,6 @@ def test_post_comparison_head_artifact_no_size_metrics(self) -> None:
in response.json()["detail"]
)
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_base_artifact_no_size_metrics(self) -> None:
"""Test POST endpoint returns 404 when base artifact has no size metrics"""
artifact_no_metrics = self.create_preprod_artifact(
@@ -529,7 +499,6 @@ def test_post_comparison_base_artifact_no_size_metrics(self) -> None:
in response.json()["detail"]
)
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_head_artifact_processing(self) -> None:
self.head_size_metric.state = PreprodArtifactSizeMetrics.SizeAnalysisState.PROCESSING
self.head_size_metric.save()
@@ -541,7 +510,6 @@ def test_post_comparison_head_artifact_processing(self) -> None:
assert data["status"] == "processing"
assert "not completed size analysis yet" in data["message"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_base_artifact_processing(self) -> None:
self.base_size_metric.state = PreprodArtifactSizeMetrics.SizeAnalysisState.PROCESSING
self.base_size_metric.save()
@@ -553,7 +521,6 @@ def test_post_comparison_base_artifact_processing(self) -> None:
assert data["status"] == "processing"
assert "not completed size analysis yet" in data["message"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_mixed_completed_and_pending_returns_202(self) -> None:
self.create_preprod_artifact_size_metrics(
self.head_artifact,
@@ -578,7 +545,6 @@ def test_post_comparison_mixed_completed_and_pending_returns_202(self) -> None:
assert data["status"] == "processing"
assert "not completed size analysis yet" in data["message"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_existing_comparison(self) -> None:
"""Test POST endpoint returns existing comparison when comparison already exists"""
# Create an existing comparison
@@ -599,7 +565,6 @@ def test_post_comparison_existing_comparison(self) -> None:
assert len(data["comparisons"]) == 1
assert data["comparisons"][0]["comparison_id"] == comparison.id
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
@patch("sentry.preprod.size_analysis.tasks.manual_size_analysis_comparison.apply_async")
def test_post_comparison_existing_failed_comparison_auto_retries(
self, mock_apply_async
@@ -626,7 +591,6 @@ def test_post_comparison_existing_failed_comparison_auto_retries(
mock_apply_async.assert_called_once()
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_cannot_compare_size_metrics(self) -> None:
"""Test POST endpoint returns 400 when size metrics cannot be compared"""
# Create additional head metric to make the lists different lengths
@@ -647,7 +611,6 @@ def test_post_comparison_cannot_compare_size_metrics(self) -> None:
assert "Head has 2 metric(s)" in detail
assert "base has 1 metric(s)" in detail
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
@patch("sentry.preprod.size_analysis.tasks.manual_size_analysis_comparison.apply_async")
def test_post_comparison_multiple_metrics(self, mock_apply_async):
"""Test POST endpoint handles multiple size metrics correctly and creates PENDING records"""
@@ -704,7 +667,6 @@ def test_post_comparison_multiple_metrics(self, mock_apply_async):
}
)
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_no_matching_base_metric(self) -> None:
"""Test POST endpoint returns 400 when head has more metrics than base"""
# Create head metric with different identifier that won't match base
@@ -725,7 +687,6 @@ def test_post_comparison_no_matching_base_metric(self) -> None:
assert "Head has 2 metric(s)" in detail
assert "base has 1 metric(s)" in detail
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_mismatched_metric_types(self) -> None:
"""Test POST endpoint returns detailed error when comparing mismatched metric types/identifiers"""
# Replace the default head metric with one that has a different identifier
@@ -754,7 +715,6 @@ def test_post_comparison_mismatched_metric_types(self) -> None:
# Should mention the identifiers involved
assert "release" in detail.lower() or "main" in detail.lower()
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_comparison_different_build_configurations(self) -> None:
"""Test POST endpoint returns 400 when artifacts have different build configurations"""
# Create a build configuration for the base artifact
@@ -774,7 +734,6 @@ def test_post_comparison_different_build_configurations(self) -> None:
)
assert response.data["detail"] == "Head and base build configurations must be the same."
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
@patch(
"sentry.preprod.api.endpoints.size_analysis.project_preprod_size_analysis_compare.get_size_retention_cutoff"
)
@@ -791,7 +750,6 @@ def test_get_returns_404_for_expired_head_artifact(self, mock_cutoff):
assert response.status_code == 404
assert response.data["detail"] == "This build's size data has expired."
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
@patch(
"sentry.preprod.api.endpoints.size_analysis.project_preprod_size_analysis_compare.get_size_retention_cutoff"
)
@@ -808,7 +766,6 @@ def test_get_returns_404_for_expired_base_artifact(self, mock_cutoff):
assert response.status_code == 404
assert response.data["detail"] == "This build's size data has expired."
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
@patch("sentry.preprod.size_analysis.tasks.manual_size_analysis_comparison.apply_async")
def test_post_rerun_as_staff_deletes_and_recreates(self, mock_apply_async):
"""Test POST with rerun=true as active staff deletes existing and creates new comparisons"""
@@ -837,7 +794,6 @@ def test_post_rerun_as_staff_deletes_and_recreates(self, mock_apply_async):
assert data["comparisons"][0]["state"] == PreprodArtifactSizeComparison.State.PENDING
mock_apply_async.assert_called_once()
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_rerun_as_non_staff_returns_403(self):
"""Test POST with rerun=true as non-staff returns 403"""
self.create_preprod_artifact_size_comparison(
@@ -853,7 +809,6 @@ def test_post_rerun_as_non_staff_returns_403(self):
assert response.status_code == 403
assert response.json()["detail"] == "Only staff can rerun comparisons."
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_post_rerun_as_inactive_staff_raises_staff_required(self):
"""Test POST with rerun=true as is_staff user without active staff session raises StaffRequired"""
self.create_preprod_artifact_size_comparison(
diff --git a/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare_download.py b/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare_download.py
index a4296bc18d5312..597e3924fef94b 100644
--- a/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare_download.py
+++ b/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_compare_download.py
@@ -1,7 +1,6 @@
from datetime import timedelta
from unittest.mock import patch
-from django.test import override_settings
from django.urls import reverse
from django.utils import timezone
@@ -13,7 +12,6 @@
from sentry.testutils.cases import TestCase
-@override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
class ProjectPreprodArtifactSizeAnalysisCompareDownloadEndpointTest(TestCase):
def setUp(self) -> None:
super().setUp()
diff --git a/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_download.py b/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_download.py
index 98b26c036321fe..814e9a435558db 100644
--- a/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_download.py
+++ b/tests/sentry/preprod/api/endpoints/size_analysis/test_project_preprod_size_analysis_download.py
@@ -2,18 +2,12 @@
from io import BytesIO
from unittest.mock import patch
-from django.test import override_settings
from django.utils import timezone
from sentry.preprod.models import PreprodArtifact, PreprodArtifactSizeMetrics
from sentry.testutils.cases import APITestCase
-@override_settings(
- SENTRY_FEATURES={
- "organizations:preprod-frontend-routes": True,
- }
-)
class ProjectPreprodArtifactSizeAnalysisDownloadEndpointTest(APITestCase):
endpoint = "sentry-api-0-organization-preprod-artifact-size-analysis-download"
diff --git a/tests/sentry/preprod/api/endpoints/test_builds.py b/tests/sentry/preprod/api/endpoints/test_builds.py
index 5c2e466cc9df07..db784c43a0027c 100644
--- a/tests/sentry/preprod/api/endpoints/test_builds.py
+++ b/tests/sentry/preprod/api/endpoints/test_builds.py
@@ -7,7 +7,6 @@
from sentry.preprod.models import PreprodArtifact, PreprodArtifactSizeMetrics
from sentry.testutils.cases import APITestCase
from sentry.testutils.helpers.datetime import before_now
-from sentry.testutils.helpers.features import with_feature
class BuildsEndpointTest(APITestCase):
@@ -30,13 +29,6 @@ def _request(self, query, token=None):
def _assert_is_successful(self, response):
assert response.status_code == 200, f"status {response.status_code} body {response.json()}"
- def test_needs_feature(self) -> None:
- response = self._request({})
- assert response.status_code == 403
- assert response.json() == {
- "detail": "Feature organizations:preprod-frontend-routes is not enabled for the organization."
- }
-
def test_invalid_token(self) -> None:
response = self._request({}, token="Invalid")
assert response.status_code == 401
@@ -59,13 +51,11 @@ def test_missing_scopes(self) -> None:
assert response.status_code == 403
assert response.json() == {"detail": "You do not have permission to perform this action."}
- @with_feature("organizations:preprod-frontend-routes")
def test_no_builds(self) -> None:
response = self._request({})
self._assert_is_successful(response)
assert response.json() == []
- @with_feature("organizations:preprod-frontend-routes")
def test_one_build(self) -> None:
self.create_preprod_artifact()
response = self._request({})
@@ -117,21 +107,18 @@ def test_one_build(self) -> None:
}
]
- @with_feature("organizations:preprod-frontend-routes")
def test_bad_project(self) -> None:
self.create_preprod_artifact()
response = self._request({"project": [1]})
assert response.status_code == 403
assert response.json() == {"detail": "You do not have permission to perform this action."}
- @with_feature("organizations:preprod-frontend-routes")
def test_bad_project_slug(self) -> None:
self.create_preprod_artifact()
response = self._request({"projectSlug": ["invalid"]})
assert response.status_code == 403
assert response.json() == {"detail": "You do not have permission to perform this action."}
- @with_feature("organizations:preprod-frontend-routes")
def test_build_in_another_project(self) -> None:
another_project = self.create_project(name="Baz", slug="baz")
self.create_preprod_artifact(project=another_project)
@@ -139,7 +126,6 @@ def test_build_in_another_project(self) -> None:
self._assert_is_successful(response)
assert response.json() == []
- @with_feature("organizations:preprod-frontend-routes")
def test_build_in_another_project_slug(self) -> None:
another_project = self.create_project(name="Baz", slug="baz")
self.create_preprod_artifact(project=another_project)
@@ -147,21 +133,18 @@ def test_build_in_another_project_slug(self) -> None:
self._assert_is_successful(response)
assert response.json() == []
- @with_feature("organizations:preprod-frontend-routes")
def test_build_in_this_project(self) -> None:
self.create_preprod_artifact()
response = self._request({"project": [self.project.id]})
self._assert_is_successful(response)
assert len(response.json()) == 1
- @with_feature("organizations:preprod-frontend-routes")
def test_build_in_this_project_slug(self) -> None:
self.create_preprod_artifact()
response = self._request({"projectSlug": [self.project.slug]})
self._assert_is_successful(response)
assert len(response.json()) == 1
- @with_feature("organizations:preprod-frontend-routes")
def test_multiple_projects(self) -> None:
project_a = self.create_project(name="AAA", slug="aaa")
self.create_preprod_artifact(project=project_a)
@@ -171,7 +154,6 @@ def test_multiple_projects(self) -> None:
self._assert_is_successful(response)
assert len(response.json()) == 2
- @with_feature("organizations:preprod-frontend-routes")
def test_multiple_project_slugs(self) -> None:
project_a = self.create_project(name="AAA", slug="aaa")
self.create_preprod_artifact(project=project_a)
@@ -181,7 +163,6 @@ def test_multiple_project_slugs(self) -> None:
self._assert_is_successful(response)
assert len(response.json()) == 2
- @with_feature("organizations:preprod-frontend-routes")
def test_per_page_respected(self) -> None:
self.create_preprod_artifact()
self.create_preprod_artifact()
@@ -189,7 +170,6 @@ def test_per_page_respected(self) -> None:
self._assert_is_successful(response)
assert len(response.json()) == 1
- @with_feature("organizations:preprod-frontend-routes")
def test_start_end_respected(self) -> None:
self.create_preprod_artifact(date_added=before_now(days=5))
middle = self.create_preprod_artifact(date_added=before_now(days=3))
@@ -200,14 +180,12 @@ def test_start_end_respected(self) -> None:
assert len(response.json()) == 1
assert response.json()[0]["id"] == str(middle.id)
- @with_feature("organizations:preprod-frontend-routes")
def test_query_invalid(self) -> None:
self.create_preprod_artifact(app_id="foo")
response = self._request({"query": "no_such_key:foo"})
assert response.status_code == 400
assert response.json() == {"detail": "Invalid key for this search: no_such_key"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_app_id_equals(self) -> None:
self.create_preprod_artifact(app_id="foo")
self.create_preprod_artifact(app_id="bar")
@@ -216,7 +194,6 @@ def test_query_app_id_equals(self) -> None:
assert len(response.json()) == 1
assert response.json()[0]["app_info"]["app_id"] == "foo"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_app_id_not_equals(self) -> None:
self.create_preprod_artifact(app_id="foo")
self.create_preprod_artifact(app_id="bar")
@@ -225,7 +202,6 @@ def test_query_app_id_not_equals(self) -> None:
assert len(response.json()) == 1
assert response.json()[0]["app_info"]["app_id"] == "bar"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_app_id_in(self) -> None:
self.create_preprod_artifact(app_id="foo")
self.create_preprod_artifact(app_id="bar")
@@ -234,7 +210,6 @@ def test_query_app_id_in(self) -> None:
assert len(response.json()) == 1
assert response.json()[0]["app_info"]["app_id"] == "foo"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_app_id_in_is_list(self) -> None:
self.create_preprod_artifact(app_id="foo")
self.create_preprod_artifact(app_id="bar")
@@ -242,7 +217,6 @@ def test_query_app_id_in_is_list(self) -> None:
self._assert_is_successful(response)
assert len(response.json()) == 0
- @with_feature("organizations:preprod-frontend-routes")
def test_query_app_id_not_in(self) -> None:
self.create_preprod_artifact(app_id="foo")
self.create_preprod_artifact(app_id="bar")
@@ -252,7 +226,6 @@ def test_query_app_id_not_in(self) -> None:
assert len(response.json()) == 1
assert response.json()[0]["app_info"]["app_id"] == "baz"
- @with_feature("organizations:preprod-frontend-routes")
def test_download_count_for_installable_artifact(self) -> None:
# Create an installable artifact (has both installable_app_file_id and build_number)
artifact = self.create_preprod_artifact(
@@ -275,7 +248,6 @@ def test_download_count_for_installable_artifact(self) -> None:
assert data[0]["distribution_info"]["download_count"] == 15
assert data[0]["distribution_info"]["is_installable"] is True
- @with_feature("organizations:preprod-frontend-routes")
def test_is_installable(self) -> None:
self.create_preprod_artifact(app_id="not_installable")
artifact = self.create_preprod_artifact(
@@ -291,7 +263,6 @@ def test_is_installable(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "installable"
- @with_feature("organizations:preprod-frontend-routes")
def test_is_not_installable(self) -> None:
self.create_preprod_artifact(app_id="not_installable")
artifact = self.create_preprod_artifact(
@@ -307,7 +278,6 @@ def test_is_not_installable(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "not_installable"
- @with_feature("organizations:preprod-frontend-routes")
def test_download_count_zero_for_non_installable_artifact(self) -> None:
# Create a non-installable artifact (no installable_app_file_id)
self.create_preprod_artifact()
@@ -319,7 +289,6 @@ def test_download_count_zero_for_non_installable_artifact(self) -> None:
assert data[0]["distribution_info"]["download_count"] == 0
assert data[0]["distribution_info"]["is_installable"] is False
- @with_feature("organizations:preprod-frontend-routes")
def test_download_count_multiple_artifacts(self) -> None:
# Create multiple installable artifacts with different download counts
artifact1 = self.create_preprod_artifact(
@@ -357,7 +326,6 @@ def test_download_count_multiple_artifacts(self) -> None:
assert app_one["distribution_info"]["download_count"] == 100
assert app_two["distribution_info"]["download_count"] == 75
- @with_feature("organizations:preprod-frontend-routes")
def test_query_install_size(self) -> None:
# Create artifacts with different install sizes via size metrics
small_artifact = self.create_preprod_artifact(app_id="small.app")
@@ -380,7 +348,6 @@ def test_query_install_size(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "small.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_build_configuration_name(self) -> None:
debug_config = self.create_preprod_build_configuration(name="Debug")
release_config = self.create_preprod_build_configuration(name="Release")
@@ -394,7 +361,6 @@ def test_query_build_configuration_name(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "debug.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_git_head_ref(self) -> None:
main_cc = self.create_commit_comparison(organization=self.organization, head_ref="main")
feature_cc = self.create_commit_comparison(
@@ -410,7 +376,6 @@ def test_query_git_head_ref(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "main.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_has_git_head_ref(self) -> None:
cc_with_branch = self.create_commit_comparison(
organization=self.organization, head_ref="main"
@@ -431,7 +396,6 @@ def test_query_has_git_head_ref(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "with_branch.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_not_has_git_head_ref(self) -> None:
cc_with_branch = self.create_commit_comparison(
organization=self.organization, head_ref="main"
@@ -453,7 +417,6 @@ def test_query_not_has_git_head_ref(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"without_branch.app", "no_cc.app"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_git_head_sha(self) -> None:
cc1 = self.create_commit_comparison(
organization=self.organization, head_sha="abc123" + "0" * 34
@@ -471,7 +434,6 @@ def test_query_git_head_sha(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "sha1.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_git_base_sha(self) -> None:
cc1 = self.create_commit_comparison(
organization=self.organization, base_sha="base111" + "1" * 33
@@ -489,7 +451,6 @@ def test_query_git_base_sha(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "base1.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_git_pr_number(self) -> None:
cc1 = self.create_commit_comparison(organization=self.organization, pr_number=123)
cc2 = self.create_commit_comparison(organization=self.organization, pr_number=456)
@@ -503,7 +464,6 @@ def test_query_git_pr_number(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "pr123.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_platform_name_apple(self) -> None:
self.create_preprod_artifact(
app_id="ios.app", artifact_type=PreprodArtifact.ArtifactType.XCARCHIVE
@@ -518,7 +478,6 @@ def test_query_platform_name_apple(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "ios.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_platform_name_android(self) -> None:
self.create_preprod_artifact(
app_id="ios.app", artifact_type=PreprodArtifact.ArtifactType.XCARCHIVE
@@ -537,7 +496,6 @@ def test_query_platform_name_android(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"android.apk", "android.aab"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_platform_name_in(self) -> None:
self.create_preprod_artifact(
app_id="ios.app", artifact_type=PreprodArtifact.ArtifactType.XCARCHIVE
@@ -556,7 +514,6 @@ def test_query_platform_name_in(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"ios.app", "android.apk", "android.aab"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_platform_name_not_in(self) -> None:
self.create_preprod_artifact(
app_id="ios.app", artifact_type=PreprodArtifact.ArtifactType.XCARCHIVE
@@ -575,7 +532,6 @@ def test_query_platform_name_not_in(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"android.apk", "android.aab"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_operator_greater_than(self) -> None:
self.create_preprod_artifact(app_id="build100.app", build_number=100)
self.create_preprod_artifact(app_id="build200.app", build_number=200)
@@ -587,7 +543,6 @@ def test_query_operator_greater_than(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "build300.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_operator_less_than(self) -> None:
self.create_preprod_artifact(app_id="build100.app", build_number=100)
self.create_preprod_artifact(app_id="build200.app", build_number=200)
@@ -599,7 +554,6 @@ def test_query_operator_less_than(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "build100.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_query_operator_greater_than_or_equal(self) -> None:
self.create_preprod_artifact(app_id="build100.app", build_number=100)
self.create_preprod_artifact(app_id="build200.app", build_number=200)
@@ -612,7 +566,6 @@ def test_query_operator_greater_than_or_equal(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"build200.app", "build300.app"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_operator_less_than_or_equal(self) -> None:
self.create_preprod_artifact(app_id="build100.app", build_number=100)
self.create_preprod_artifact(app_id="build200.app", build_number=200)
@@ -625,7 +578,6 @@ def test_query_operator_less_than_or_equal(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"build100.app", "build200.app"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_operator_contains(self) -> None:
cc1 = self.create_commit_comparison(
organization=self.organization, head_ref="feature/add-login"
@@ -648,7 +600,6 @@ def test_query_operator_contains(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"login.app", "signup.app"}
- @with_feature("organizations:preprod-frontend-routes")
def test_query_operator_not_contains(self) -> None:
cc1 = self.create_commit_comparison(
organization=self.organization, head_ref="feature/add-login"
@@ -669,7 +620,6 @@ def test_query_operator_not_contains(self) -> None:
data = response.json()
assert data[0]["app_info"]["app_id"] == "crash.app"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_app_id(self) -> None:
self.create_preprod_artifact(app_id="com.example.myapp")
self.create_preprod_artifact(app_id="com.other.app")
@@ -681,7 +631,6 @@ def test_free_text_search_app_id(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "com.example.myapp"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_app_name(self) -> None:
self.create_preprod_artifact(app_id="com.example.one", app_name="MyAwesomeApp")
self.create_preprod_artifact(app_id="com.example.two", app_name="OtherApp")
@@ -692,7 +641,6 @@ def test_free_text_search_app_name(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "com.example.one"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_build_version(self) -> None:
self.create_preprod_artifact(app_id="app1", build_version="1.2.3-beta")
self.create_preprod_artifact(app_id="app2", build_version="2.0.0-release")
@@ -703,7 +651,6 @@ def test_free_text_search_build_version(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "app1"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_commit_sha(self) -> None:
cc1 = self.create_commit_comparison(
organization=self.organization, head_sha="abc123def456" + "0" * 28
@@ -721,7 +668,6 @@ def test_free_text_search_commit_sha(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "app1"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_branch(self) -> None:
cc1 = self.create_commit_comparison(
organization=self.organization, head_ref="feature/new-login"
@@ -739,7 +685,6 @@ def test_free_text_search_branch(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "app1"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_pr_number(self) -> None:
cc1 = self.create_commit_comparison(organization=self.organization, pr_number=12345)
cc2 = self.create_commit_comparison(organization=self.organization, pr_number=67890)
@@ -753,7 +698,6 @@ def test_free_text_search_pr_number(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "app1"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_by_build_id(self) -> None:
artifact1 = self.create_preprod_artifact(app_id="app1")
self.create_preprod_artifact(app_id="app2")
@@ -764,7 +708,6 @@ def test_free_text_search_by_build_id(self) -> None:
assert len(data) == 1
assert data[0]["id"] == str(artifact1.id)
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_no_matches(self) -> None:
self.create_preprod_artifact(app_id="com.example.app")
self.create_preprod_artifact(app_id="com.other.app")
@@ -774,7 +717,6 @@ def test_free_text_search_no_matches(self) -> None:
data = response.json()
assert len(data) == 0
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_empty_query(self) -> None:
self.create_preprod_artifact(app_id="app1")
self.create_preprod_artifact(app_id="app2")
@@ -784,7 +726,6 @@ def test_free_text_search_empty_query(self) -> None:
data = response.json()
assert len(data) == 2
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_whitespace_only(self) -> None:
self.create_preprod_artifact(app_id="app1")
self.create_preprod_artifact(app_id="app2")
@@ -794,7 +735,6 @@ def test_free_text_search_whitespace_only(self) -> None:
data = response.json()
assert len(data) == 2
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_case_insensitive(self) -> None:
self.create_preprod_artifact(app_id="com.Example.MyApp")
@@ -804,7 +744,6 @@ def test_free_text_search_case_insensitive(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "com.Example.MyApp"
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_multiple_matches(self) -> None:
self.create_preprod_artifact(app_id="com.test.one", app_name="TestApp")
self.create_preprod_artifact(app_id="com.test.two", build_version="1.0-test")
@@ -816,7 +755,6 @@ def test_free_text_search_multiple_matches(self) -> None:
app_ids = {d["app_info"]["app_id"] for d in data}
assert app_ids == {"com.test.one", "com.test.two"}
- @with_feature("organizations:preprod-frontend-routes")
def test_free_text_search_with_structured_filter(self) -> None:
cc = self.create_commit_comparison(
organization=self.organization, head_ref="feature/awesome"
@@ -838,7 +776,6 @@ def test_free_text_search_with_structured_filter(self) -> None:
assert len(data) == 1
assert data[0]["app_info"]["app_id"] == "com.example.android"
- @with_feature("organizations:preprod-frontend-routes")
def test_size_state_filter(self) -> None:
artifact_not_ran = self.create_preprod_artifact(app_id="not_ran.app")
self.create_preprod_artifact_size_metrics(
@@ -866,7 +803,6 @@ def test_size_state_filter(self) -> None:
self._assert_is_successful(response)
assert len(response.json()) == 2
- @with_feature("organizations:preprod-frontend-routes")
def test_size_state_filter_mixed_metrics(self) -> None:
artifact = self.create_preprod_artifact(app_id="mixed.app")
self.create_preprod_artifact_size_metrics(
@@ -883,13 +819,11 @@ def test_size_state_filter_mixed_metrics(self) -> None:
self._assert_is_successful(response)
assert len(response.json()) == 0
- @with_feature("organizations:preprod-frontend-routes")
def test_size_state_invalid_values(self) -> None:
self.create_preprod_artifact(app_id="test.app")
assert self._request({"query": "size_state:bogus"}).status_code == 400
assert self._request({"query": "size_state:[bogus, completed]"}).status_code == 400
- @with_feature("organizations:preprod-frontend-routes")
def test_distribution_error_code_filter(self) -> None:
self.create_preprod_artifact(
app_id="quota.app",
@@ -920,12 +854,10 @@ def test_distribution_error_code_filter(self) -> None:
self._assert_is_successful(response)
assert len(response.json()) == 2
- @with_feature("organizations:preprod-frontend-routes")
def test_distribution_error_code_invalid_values(self) -> None:
self.create_preprod_artifact(app_id="test.app")
assert self._request({"query": "distribution_error_code:bogus"}).status_code == 400
- @with_feature("organizations:preprod-frontend-routes")
@patch("sentry.preprod.api.endpoints.builds.get_size_retention_cutoff")
def test_excludes_expired_artifacts(self, mock_cutoff) -> None:
mock_cutoff.return_value = before_now(days=30)
diff --git a/tests/sentry/preprod/api/endpoints/test_organization_preprod_artifact_assemble.py b/tests/sentry/preprod/api/endpoints/test_organization_preprod_artifact_assemble.py
index e4db4f7a16e2f8..8f49dd2e737e94 100644
--- a/tests/sentry/preprod/api/endpoints/test_organization_preprod_artifact_assemble.py
+++ b/tests/sentry/preprod/api/endpoints/test_organization_preprod_artifact_assemble.py
@@ -19,7 +19,6 @@
from sentry.silo.base import SiloMode
from sentry.tasks.assemble import AssembleTask, ChunkFileState, set_assemble_status
from sentry.testutils.cases import APITestCase, TestCase
-from sentry.testutils.helpers.features import Feature
from sentry.testutils.outbox import outbox_runner
from sentry.testutils.silo import assume_test_silo_mode
from sentry.utils.security.orgauthtoken_token import generate_token, hash_token
@@ -353,34 +352,6 @@ def setUp(self) -> None:
args=[self.organization.slug, self.project.slug],
)
- self.feature_context = Feature("organizations:preprod-frontend-routes")
- self.feature_context.__enter__()
-
- def tearDown(self) -> None:
- self.feature_context.__exit__(None, None, None)
- super().tearDown()
-
- def test_feature_flag_disabled_returns_403(self) -> None:
- """Test that endpoint returns 404 when feature flag is disabled."""
- self.feature_context.__exit__(None, None, None)
-
- try:
- content = b"test content"
- total_checksum = sha1(content).hexdigest()
-
- response = self.client.post(
- self.url,
- data={
- "checksum": total_checksum,
- "chunks": [],
- },
- HTTP_AUTHORIZATION=f"Bearer {self.token.token}",
- )
- assert response.status_code == 403
- finally:
- self.feature_context = Feature("organizations:preprod-frontend-routes")
- self.feature_context.__enter__()
-
def test_assemble_json_schema_integration(self) -> None:
"""Integration test for schema validation through the endpoint."""
response = self.client.post(
diff --git a/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_delete.py b/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_delete.py
index 1f5dd3910165e7..be851a7feb9dee 100644
--- a/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_delete.py
+++ b/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_delete.py
@@ -1,5 +1,3 @@
-from django.test import override_settings
-
from sentry.models.files.file import File
from sentry.preprod.models import (
InstallablePreprodArtifact,
@@ -19,7 +17,6 @@ def setUp(self) -> None:
self.project = self.create_project(organization=self.organization)
self.login_as(user=self.user)
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_delete_artifact_success(self) -> None:
main_file = self.create_file(name="test_artifact.zip", type="application/zip")
installable_file = self.create_file(name="test_app.ipa", type="application/octet-stream")
@@ -70,7 +67,6 @@ def test_delete_artifact_success(self) -> None:
assert not PreprodArtifactSizeMetrics.objects.filter(id=size_metric.id).exists()
assert not InstallablePreprodArtifact.objects.filter(id=installable.id).exists()
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_delete_artifact_not_found(self) -> None:
response = self.get_error_response(
self.organization.slug,
@@ -80,23 +76,6 @@ def test_delete_artifact_not_found(self) -> None:
assert "The requested head preprod artifact does not exist" in response.data["detail"]
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": False})
- def test_delete_artifact_feature_disabled(self) -> None:
- artifact = self.create_preprod_artifact(
- app_name="test_artifact",
- app_id="com.test.app",
- build_version="1.0.0",
- build_number=1,
- )
- response = self.get_error_response(
- self.organization.slug,
- artifact.id,
- status_code=403,
- )
-
- assert response.data["error"] == "Feature not enabled"
-
- @override_settings(SENTRY_FEATURES={"organizations:preprod-frontend-routes": True})
def test_delete_artifact_minimal(self) -> None:
"""Test deleting an artifact with only the minimum required fields"""
# Create the preprod artifact without optional files
diff --git a/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_download.py b/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_download.py
index c38fc224de424b..83ee3fc94646db 100644
--- a/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_download.py
+++ b/tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_download.py
@@ -72,8 +72,7 @@ def test_download_preprod_artifact_no_file(self) -> None:
headers = self._get_authenticated_request_headers(url)
- with self.feature("organizations:preprod-frontend-routes"):
- response = self.client.get(url, **headers)
+ response = self.client.get(url, **headers)
assert response.status_code == 404
assert response.json()["detail"] == "The requested resource does not exist"
diff --git a/tests/sentry/preprod/api/endpoints/test_project_preprod_build_details.py b/tests/sentry/preprod/api/endpoints/test_project_preprod_build_details.py
index 77f15ee2fe65d9..771537615161af 100644
--- a/tests/sentry/preprod/api/endpoints/test_project_preprod_build_details.py
+++ b/tests/sentry/preprod/api/endpoints/test_project_preprod_build_details.py
@@ -49,15 +49,6 @@ def setUp(self) -> None:
build_number=42,
)
- # Enable the feature flag for all tests by default
- self.feature_context = self.feature({"organizations:preprod-frontend-routes": True})
- self.feature_context.__enter__()
-
- def tearDown(self) -> None:
- # Exit the feature flag context manager
- self.feature_context.__exit__(None, None, None)
- super().tearDown()
-
def _get_url(self, artifact_id=None):
artifact_id = artifact_id or self.preprod_artifact.id
return reverse(
@@ -127,15 +118,6 @@ def test_get_build_details_not_found(self) -> None:
assert response.status_code == 404
assert "The requested head preprod artifact does not exist" in response.json()["detail"]
- def test_get_build_details_feature_flag_disabled(self) -> None:
- with self.feature({"organizations:preprod-frontend-routes": False}):
- url = self._get_url()
- response = self.client.get(
- url, format="json", HTTP_AUTHORIZATION=f"Bearer {self.api_token.token}"
- )
- assert response.status_code == 403
- assert response.json()["error"] == "Feature not enabled"
-
def test_get_build_details_dates_and_types(self) -> None:
url = self._get_url()
response = self.client.get(
diff --git a/tests/sentry/preprod/api/endpoints/test_project_preprod_check_for_updates.py b/tests/sentry/preprod/api/endpoints/test_project_preprod_check_for_updates.py
index 32092e37b4d1ad..40a9204b076092 100644
--- a/tests/sentry/preprod/api/endpoints/test_project_preprod_check_for_updates.py
+++ b/tests/sentry/preprod/api/endpoints/test_project_preprod_check_for_updates.py
@@ -28,15 +28,6 @@ def setUp(self) -> None:
self.file = self.create_file(name="test_artifact.apk", type="application/octet-stream")
- # Enable the feature flag for all tests by default
- self.feature_context = self.feature({"organizations:preprod-frontend-routes": True})
- self.feature_context.__enter__()
-
- def tearDown(self) -> None:
- # Exit the feature flag context manager
- self.feature_context.__exit__(None, None, None)
- super().tearDown()
-
def _get_url(self):
return reverse(
"sentry-api-0-project-preprod-check-for-updates",
diff --git a/tests/snuba/api/endpoints/test_organization_events_preprod_size.py b/tests/snuba/api/endpoints/test_organization_events_preprod_size.py
index 4ba9c5d5659488..e584d2a044a562 100644
--- a/tests/snuba/api/endpoints/test_organization_events_preprod_size.py
+++ b/tests/snuba/api/endpoints/test_organization_events_preprod_size.py
@@ -20,7 +20,7 @@ def setUp(self) -> None:
def _do_request(self, data, features=None):
if features is None:
- features = {"organizations:preprod-frontend-routes": True}
+ features = {}
features.update(self.features)
url = reverse(
"sentry-api-0-organization-events",
diff --git a/tests/snuba/api/endpoints/test_organization_events_stats_preprod_size.py b/tests/snuba/api/endpoints/test_organization_events_stats_preprod_size.py
index 587440d9ef16f1..5b42b558aa9a37 100644
--- a/tests/snuba/api/endpoints/test_organization_events_stats_preprod_size.py
+++ b/tests/snuba/api/endpoints/test_organization_events_stats_preprod_size.py
@@ -27,7 +27,7 @@ def setUp(self) -> None:
def _do_request(self, data, url=None, features=None):
if features is None:
- features = {"organizations:preprod-frontend-routes": True}
+ features = {}
features.update(self.features)
with self.feature(features):
return self.client.get(self.url if url is None else url, data=data, format="json")