From f2ce3ed21724a8db2bc04abccc9b8d0cc3f258e1 Mon Sep 17 00:00:00 2001 From: Rudra Patel Date: Thu, 20 Aug 2026 15:17:12 -0700 Subject: [PATCH] ref(incidents): Ungate the alert rule endpoint base classes bases.py carried the same gate four times, each with a request.method != "DELETE" carve-out so downgraded orgs could still delete metric alerts. With the gate gone the carve-out goes too, which makes the DELETE test_no_feature a duplicate of test_simple. --- src/sentry/incidents/endpoints/bases.py | 24 ------------------- .../test_organization_alert_rule_details.py | 15 ------------ .../test_project_alert_rule_details.py | 21 +++++++--------- 3 files changed, 8 insertions(+), 52 deletions(-) diff --git a/src/sentry/incidents/endpoints/bases.py b/src/sentry/incidents/endpoints/bases.py index 7e9c70aaf975..49ada3f44c09 100644 --- a/src/sentry/incidents/endpoints/bases.py +++ b/src/sentry/incidents/endpoints/bases.py @@ -61,12 +61,6 @@ def convert_args( project = kwargs["project"] validated_alert_rule_id = to_valid_int_id("alert_rule_id", alert_rule_id, raise_404=True) - # Allow orgs that have downgraded plans to delete metric alerts - if request.method != "DELETE" and not features.has( - "organizations:incidents", project.organization, actor=request.user - ): - raise ResourceDoesNotExist - if not request.access.has_project_access(project): raise PermissionDenied @@ -90,12 +84,6 @@ def convert_args( organization = kwargs["organization"] validated_alert_rule_id = to_valid_int_id("alert_rule_id", alert_rule_id, raise_404=True) - # Allow orgs that have downgraded plans to delete metric alerts - if request.method != "DELETE" and not features.has( - "organizations:incidents", organization, actor=request.user - ): - raise ResourceDoesNotExist - try: kwargs["alert_rule"] = AlertRule.objects.get( organization=organization, id=validated_alert_rule_id @@ -114,12 +102,6 @@ def convert_args( project = kwargs["project"] validated_alert_rule_id = to_valid_int_id("alert_rule_id", alert_rule_id, raise_404=True) - # Allow orgs that have downgraded plans to delete metric alerts - if request.method != "DELETE" and not features.has( - "organizations:incidents", project.organization, actor=request.user - ): - raise ResourceDoesNotExist - if not request.access.has_project_access(project): raise PermissionDenied @@ -165,12 +147,6 @@ def convert_args( organization = kwargs["organization"] validated_alert_rule_id = to_valid_int_id("alert_rule_id", alert_rule_id, raise_404=True) - # Allow orgs that have downgraded plans to delete metric alerts - if request.method != "DELETE" and not features.has( - "organizations:incidents", organization, actor=request.user - ): - raise ResourceDoesNotExist - if request.method in ("GET", "DELETE") or features.has( "organizations:workflow-engine-rule-serializers", organization ): diff --git a/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py b/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py index 13e0e50f1dfc..135cb371219f 100644 --- a/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py +++ b/tests/sentry/incidents/endpoints/test_organization_alert_rule_details.py @@ -222,14 +222,6 @@ def test_permissions(self) -> None: assert resp.status_code == 403 - def test_no_feature(self) -> None: - self.create_member( - user=self.user, organization=self.organization, role="owner", teams=[self.team] - ) - self.login_as(self.user) - resp = self.get_response(self.organization.slug, self.alert_rule.id) - assert resp.status_code == 404 - def test_no_project(self) -> None: self.create_team(organization=self.organization, members=[self.user]) self.login_as(self.user) @@ -2723,13 +2715,6 @@ def test_simple(self) -> None: == list(audit_log_entry)[0].ip_address ) - def test_no_feature(self) -> None: - self.create_member( - user=self.user, organization=self.organization, role="owner", teams=[self.team] - ) - self.login_as(self.user) - self.get_success_response(self.organization.slug, self.alert_rule.id, status_code=204) - def test_snapshot_and_create_new_with_same_name(self) -> None: with self.tasks(): self.create_member( diff --git a/tests/sentry/incidents/endpoints/test_project_alert_rule_details.py b/tests/sentry/incidents/endpoints/test_project_alert_rule_details.py index 4a5f2ebc1b23..2c5d0552b698 100644 --- a/tests/sentry/incidents/endpoints/test_project_alert_rule_details.py +++ b/tests/sentry/incidents/endpoints/test_project_alert_rule_details.py @@ -37,7 +37,7 @@ def setUp(self) -> None: class AlertRuleDetailsGetEndpointTest(AlertRuleDetailsBase): def test_dual_written_resolves_detector(self) -> None: - with self.feature("organizations:incidents"), outbox_runner(): + with outbox_runner(): resp = self.get_success_response( self.organization.slug, self.project.slug, self.alert_rule.id ) @@ -48,16 +48,12 @@ def test_single_written_resolves_via_fake_id(self) -> None: # Simulate a single-written detector by removing the AlertRuleDetector bridge. AlertRuleDetector.objects.filter(detector=self.detector).delete() fake_id = get_fake_id_from_object_id(self.detector.id) - with self.feature("organizations:incidents"): - resp = self.get_success_response(self.organization.slug, self.project.slug, fake_id) + resp = self.get_success_response(self.organization.slug, self.project.slug, fake_id) assert resp.data["name"] == self.detector.name def test_single_written_fake_id_not_found_returns_404(self) -> None: fake_id = get_fake_id_from_object_id(999999999) - with self.feature("organizations:incidents"): - self.get_error_response( - self.organization.slug, self.project.slug, fake_id, status_code=404 - ) + self.get_error_response(self.organization.slug, self.project.slug, fake_id, status_code=404) class AlertRuleDetailsPutEndpointTest(AlertRuleDetailsBase): @@ -89,7 +85,7 @@ def _put_payload(self) -> dict[str, Any]: def test_simple(self) -> None: alert_rule = self.alert_rule - with self.feature("organizations:incidents"), outbox_runner(): + with outbox_runner(): resp = self.get_success_response( self.organization.slug, self.project.slug, alert_rule.id, **self._put_payload() ) @@ -114,15 +110,14 @@ def test_single_written_detector_deleted(self) -> None: AlertRuleDetector.objects.filter(detector=self.detector).delete() fake_id = get_fake_id_from_object_id(self.detector.id) - with self.feature("organizations:incidents"): - self.get_success_response( - self.organization.slug, self.project.slug, fake_id, status_code=204 - ) + self.get_success_response( + self.organization.slug, self.project.slug, fake_id, status_code=204 + ) assert not Detector.objects.filter(id=self.detector.id).exists() def test_dual_written_detector_deleted(self) -> None: - with self.feature("organizations:incidents"), outbox_runner(): + with outbox_runner(): self.get_success_response( self.organization.slug, self.project.slug, self.alert_rule.id, status_code=204 )