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")