diff --git a/src/sentry/digests/notifications.py b/src/sentry/digests/notifications.py index d8f2bd2596f26a..87a46abb25c342 100644 --- a/src/sentry/digests/notifications.py +++ b/src/sentry/digests/notifications.py @@ -89,7 +89,7 @@ def event_to_record( assert event.group is not None rule_ids = [] identifier_key = IdentifierKey.RULE - if features.has("organizations:workflow-engine-ui-links", event.organization): + if features.has("organizations:workflow-engine-ui", event.organization): identifier_key = IdentifierKey.WORKFLOW for rule in rules: rule_ids.append(int(get_key_from_rule_data(rule, "workflow_id"))) @@ -194,7 +194,7 @@ def get_rules_from_workflows(project: Project, workflow_ids: set[int]) -> dict[i # We are only processing the workflows in the digest if under the new flag # This should be ok since we should only add workflow_ids to redis when under this flag - if features.has("organizations:workflow-engine-ui-links", project.organization): + if features.has("organizations:workflow-engine-ui", project.organization): for workflow_id, workflow in workflows.items(): assert ( workflow.organization_id == project.organization_id diff --git a/src/sentry/incidents/action_handlers.py b/src/sentry/incidents/action_handlers.py index 352e39a82e5565..1aafa160e7a052 100644 --- a/src/sentry/incidents/action_handlers.py +++ b/src/sentry/incidents/action_handlers.py @@ -582,7 +582,7 @@ def generate_incident_trigger_email_context( if notification_uuid: alert_link_params["notification_uuid"] = notification_uuid - if features.has("organizations:workflow-engine-ui-links", organization): + if features.has("organizations:workflow-engine-ui", organization): assert ( metric_issue_context.group is not None ), "Group should not be None when workflow engine ui links are enabled" @@ -632,7 +632,7 @@ def generate_incident_trigger_email_context( snooze_alert = False # We don't have user muting for workflows in the new workflow engine system # so we don't need to show the snooze alert url - if not features.has("organizations:workflow-engine-ui-links", organization): + if not features.has("organizations:workflow-engine-ui", organization): snooze_alert = True snooze_alert_url = alert_link + "&" + urlencode({"mute": "1"}) diff --git a/src/sentry/incidents/grouptype.py b/src/sentry/incidents/grouptype.py index 560099f4760afc..ea36e0542008f6 100644 --- a/src/sentry/incidents/grouptype.py +++ b/src/sentry/incidents/grouptype.py @@ -354,3 +354,15 @@ class MetricIssue(GroupType): }, }, ) + + @classmethod + def allow_ingest(cls, organization: Organization) -> bool: + return True + + @classmethod + def allow_post_process_group(cls, organization: Organization) -> bool: + return True + + @classmethod + def build_visible_feature_name(cls) -> str: + return "organizations:workflow-engine-ui" diff --git a/src/sentry/integrations/discord/message_builder/issues.py b/src/sentry/integrations/discord/message_builder/issues.py index 10f8601fae07fc..59e9085962138c 100644 --- a/src/sentry/integrations/discord/message_builder/issues.py +++ b/src/sentry/integrations/discord/message_builder/issues.py @@ -62,7 +62,7 @@ def build(self, notification_uuid: str | None = None) -> DiscordMessage: rule_environment_id = None if self.rules: rule_environment_id = self.rules[0].environment_id - if features.has("organizations:workflow-engine-ui-links", self.group.organization): + if features.has("organizations:workflow-engine-ui", self.group.organization): rule_id = int(get_key_from_rule_data(self.rules[0], "workflow_id")) elif should_fire_workflow_actions(self.group.organization, self.group.type): rule_id = int(get_key_from_rule_data(self.rules[0], "legacy_rule_id")) @@ -71,7 +71,7 @@ def build(self, notification_uuid: str | None = None) -> DiscordMessage: url = None - if features.has("organizations:workflow-engine-ui-links", self.group.organization): + if features.has("organizations:workflow-engine-ui", self.group.organization): url = get_title_link_workflow_engine_ui( self.group, self.event, diff --git a/src/sentry/integrations/messaging/message_builder.py b/src/sentry/integrations/messaging/message_builder.py index 540137c483520c..f60ea6e8e432f2 100644 --- a/src/sentry/integrations/messaging/message_builder.py +++ b/src/sentry/integrations/messaging/message_builder.py @@ -292,7 +292,7 @@ def build_footer( ) -> str: footer = f"{group.qualified_short_id}" if rules: - if features.has("organizations:workflow-engine-ui-links", group.organization): + if features.has("organizations:workflow-engine-ui", group.organization): rule_url = absolute_uri( create_link_to_workflow( group.organization.id, get_key_from_rule_data(rules[0], "workflow_id") diff --git a/src/sentry/integrations/metric_alerts.py b/src/sentry/integrations/metric_alerts.py index 8bf70227cef85e..a000801f83d6bc 100644 --- a/src/sentry/integrations/metric_alerts.py +++ b/src/sentry/integrations/metric_alerts.py @@ -253,7 +253,7 @@ def incident_attachment_info( title_link = build_title_link(alert_rule_id, organization, workflow_engine_params) - elif features.has("organizations:workflow-engine-ui-links", organization): + elif features.has("organizations:workflow-engine-ui", organization): if metric_issue_context.group is None: raise ValueError("Group is required for workflow engine UI links") diff --git a/src/sentry/integrations/opsgenie/client.py b/src/sentry/integrations/opsgenie/client.py index bb2c16c462ff62..be319ff4ee214d 100644 --- a/src/sentry/integrations/opsgenie/client.py +++ b/src/sentry/integrations/opsgenie/client.py @@ -92,7 +92,7 @@ def build_issue_alert_payload( if notification_uuid: group_params["notification_uuid"] = notification_uuid rule_workflow_context = {} - if features.has("organizations:workflow-engine-ui-links", group.project.organization): + if features.has("organizations:workflow-engine-ui", group.project.organization): workflow_urls = self._get_workflow_urls(group, rules) rule_workflow_context = { "Triggering Workflows": ", ".join([rule.label for rule in rules]), diff --git a/src/sentry/integrations/slack/message_builder/issues.py b/src/sentry/integrations/slack/message_builder/issues.py index b4df09b3ed839f..8cef180a0b5728 100644 --- a/src/sentry/integrations/slack/message_builder/issues.py +++ b/src/sentry/integrations/slack/message_builder/issues.py @@ -666,7 +666,7 @@ def build(self, notification_uuid: str | None = None) -> SlackBlock: rule_id = None rule_environment_id = None if self.rules: - if features.has("organizations:workflow-engine-ui-links", self.group.organization): + if features.has("organizations:workflow-engine-ui", self.group.organization): rule_id = int(get_key_from_rule_data(self.rules[0], "workflow_id")) elif should_fire_workflow_actions(self.group.organization, self.group.type): rule_id = int(get_key_from_rule_data(self.rules[0], "legacy_rule_id")) @@ -680,7 +680,7 @@ def build(self, notification_uuid: str | None = None) -> SlackBlock: has_action = True title_link = None - if features.has("organizations:workflow-engine-ui-links", self.group.organization): + if features.has("organizations:workflow-engine-ui", self.group.organization): title_link = get_title_link_workflow_engine_ui( self.group, self.event, diff --git a/src/sentry/integrations/slack/message_builder/util.py b/src/sentry/integrations/slack/message_builder/util.py index 5e8c313568d8f1..bd6a3dc95e7a4e 100644 --- a/src/sentry/integrations/slack/message_builder/util.py +++ b/src/sentry/integrations/slack/message_builder/util.py @@ -19,7 +19,7 @@ def build_slack_footer( footer = f"{group.qualified_short_id}" if rules: - if features.has("organizations:workflow-engine-ui-links", group.organization): + if features.has("organizations:workflow-engine-ui", group.organization): rule_url = absolute_uri( create_link_to_workflow( group.organization.id, get_key_from_rule_data(rules[0], "workflow_id") diff --git a/src/sentry/notifications/notification_action/types.py b/src/sentry/notifications/notification_action/types.py index 07f13d4a173546..eded30872f78ca 100644 --- a/src/sentry/notifications/notification_action/types.py +++ b/src/sentry/notifications/notification_action/types.py @@ -196,11 +196,9 @@ def create_rule_instance_from_action( workflow_id = getattr(action, "workflow_id", None) label = detector.name - # We need to pass the legacy rule id when the workflow-engine-ui-links feature flag is disabled + # We need to pass the legacy rule id when the workflow-engine-ui feature flag is disabled # This is so we can build the old link to the rule - if not features.has( - "organizations:workflow-engine-ui-links", detector.project.organization - ): + if not features.has("organizations:workflow-engine-ui", detector.project.organization): if workflow_id is None: raise ValueError("Workflow ID is required when triggering an action") diff --git a/src/sentry/notifications/notifications/digest.py b/src/sentry/notifications/notifications/digest.py index 2c2bbd89975f2b..93b53c2c34867e 100644 --- a/src/sentry/notifications/notifications/digest.py +++ b/src/sentry/notifications/notifications/digest.py @@ -148,7 +148,7 @@ def get_context(self) -> MutableMapping[str, Any]: sentry_query_params = self.get_sentry_query_params(ExternalProviders.EMAIL) - if not features.has("organizations:workflow-engine-ui-links", self.project.organization): + if not features.has("organizations:workflow-engine-ui", self.project.organization): # TODO(iamrajjoshi): This actually mutes a rule for a user, something we have not ported over in the new system # By not including this context, the template will not show the mute button snooze_alert = len(rule_details) > 0 diff --git a/src/sentry/notifications/notifications/rules.py b/src/sentry/notifications/notifications/rules.py index e9f6863fe3440d..4f95a4aa06a7fb 100644 --- a/src/sentry/notifications/notifications/rules.py +++ b/src/sentry/notifications/notifications/rules.py @@ -261,7 +261,7 @@ def get_context(self) -> MutableMapping[str, Any]: # We don't show the snooze alert if the organization has not enabled the workflow engine UI links # This is because in the new UI/system a user can't individually disable a workflow - if not features.has("organizations:workflow-engine-ui-links", self.organization): + if not features.has("organizations:workflow-engine-ui", self.organization): if len(self.rules) > 0: context["snooze_alert"] = True context["snooze_alert_url"] = get_snooze_url( @@ -299,7 +299,7 @@ def get_notification_title( title_str = "Alert triggered" if self.rules: - if features.has("organizations:workflow-engine-ui-links", self.organization): + if features.has("organizations:workflow-engine-ui", self.organization): rule_url = absolute_uri( create_link_to_workflow( self.organization.id, get_key_from_rule_data(self.rules[0], "workflow_id") diff --git a/src/sentry/notifications/utils/links.py b/src/sentry/notifications/utils/links.py index 731b56af4ab2ad..3895f3734b14ec 100644 --- a/src/sentry/notifications/utils/links.py +++ b/src/sentry/notifications/utils/links.py @@ -108,7 +108,7 @@ def get_rules( ) -> Sequence[NotificationRuleDetails]: from sentry.notifications.notification_action.utils import should_fire_workflow_actions - if features.has("organizations:workflow-engine-ui-links", organization): + if features.has("organizations:workflow-engine-ui", organization): return get_workflow_links(rules, organization, project) elif type_id is None or should_fire_workflow_actions(organization, type_id): return get_rules_with_legacy_ids(rules, organization, project) diff --git a/src/sentry/rules/actions/integrations/create_ticket/utils.py b/src/sentry/rules/actions/integrations/create_ticket/utils.py index af0b1b78029c88..41b3de3a378be4 100644 --- a/src/sentry/rules/actions/integrations/create_ticket/utils.py +++ b/src/sentry/rules/actions/integrations/create_ticket/utils.py @@ -143,7 +143,7 @@ def create_issue(event: GroupEvent, futures: Sequence[RuleFuture]) -> None: installation, IssueBasicIntegration ), "Installation must be an IssueBasicIntegration to create a ticket" data["title"] = installation.get_group_title(event.group, event) - if features.has("organizations:workflow-engine-ui-links", organization): + if features.has("organizations:workflow-engine-ui", organization): workflow_id = data.get("workflow_id") assert workflow_id is not None data["description"] = build_description_workflow_engine_ui( diff --git a/src/sentry/sentry_apps/tasks/sentry_apps.py b/src/sentry/sentry_apps/tasks/sentry_apps.py index a3c86e027a6e0e..115a65b0fdfc21 100644 --- a/src/sentry/sentry_apps/tasks/sentry_apps.py +++ b/src/sentry/sentry_apps/tasks/sentry_apps.py @@ -742,7 +742,7 @@ def notify_sentry_app(event: GroupEvent, futures: Sequence[RuleFuture]): # if we are using the new workflow engine, we need to use the legacy rule id # Ignore test notifications if int(id) != -1: - if features.has("organizations:workflow-engine-ui-links", event.group.organization): + if features.has("organizations:workflow-engine-ui", event.group.organization): id = get_key_from_rule_data(f.rule, "workflow_id") elif should_fire_workflow_actions(event.group.organization, event.group.type): id = get_key_from_rule_data(f.rule, "legacy_rule_id") diff --git a/tests/sentry/digests/test_utilities.py b/tests/sentry/digests/test_utilities.py index 59856825b7ca40..c5a03ec0ea0a84 100644 --- a/tests/sentry/digests/test_utilities.py +++ b/tests/sentry/digests/test_utilities.py @@ -65,7 +65,7 @@ def test_get_event_from_groups_in_digest(self) -> None: # Make sure that the target_identifier = RULE assert {record.value.identifier_key == IdentifierKey.RULE for record in records} - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_event_to_record_with_workflow_id(self) -> None: project = self.create_project(fire_project_created=True) workflow = self.create_workflow(organization=self.organization) @@ -242,7 +242,7 @@ def test_simple(self) -> None: assert_get_personalized_digests(self.project, digest, expected_result) - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_simple_with_workflow_id(self) -> None: records = [ event_to_record(event, (self.rule_with_workflow_id,)) @@ -286,7 +286,7 @@ def test_direct_email(self) -> None: self.project, digest, expected_result, ActionTargetType.MEMBER, self.user1.id ) - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_direct_email_with_workflow_id(self) -> None: """When the action type is not Issue Owners, then the target actor gets a digest. - Workflow ID""" self.project_ownership.update(fallthrough=False) @@ -339,7 +339,7 @@ def test_team_without_members(self) -> None: actor for actors in participants_by_provider_by_event.values() for actor in actors } # no users in this team no digests should be processed - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_team_without_members_with_workflow_id(self) -> None: team = self.create_team() project = self.create_project(teams=[team], fire_project_created=True) @@ -422,7 +422,7 @@ def test_everyone_with_owners(self) -> None: } assert_get_personalized_digests(self.project, digest, expected_result) - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_everyone_with_owners_with_workflow_id(self) -> None: events = self.create_events_from_filenames( self.project, ["hello.moz", "goodbye.moz", "hola.moz", "adios.moz"] @@ -468,7 +468,7 @@ def test_simple_with_workflow_id_flag_off_fallback(self) -> None: """ self.create_alert_rule_workflow(workflow=self.workflow, rule_id=self.shadow_rule.id) - with self.feature("organizations:workflow-engine-ui-links"): + with self.feature("organizations:workflow-engine-ui"): records = [ event_to_record(event, (self.rule_with_workflow_id,)) for event in self.team1_events + self.team2_events + self.user4_events diff --git a/tests/sentry/integrations/opsgenie/test_client.py b/tests/sentry/integrations/opsgenie/test_client.py index 6a8197508131f5..309ee8cf71b01c 100644 --- a/tests/sentry/integrations/opsgenie/test_client.py +++ b/tests/sentry/integrations/opsgenie/test_client.py @@ -186,7 +186,7 @@ def test_send_notification_with_workflow_engine_trigger_actions( @responses.activate @patch("sentry.integrations.utils.metrics.EventLifecycle.record_event") - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_send_notification_with_workflow_engine_ui_links(self, mock_record: MagicMock) -> None: resp_data = { "result": "Request will be processed", diff --git a/tests/sentry/integrations/slack/actions/notification/test_slack_notify_service_action.py b/tests/sentry/integrations/slack/actions/notification/test_slack_notify_service_action.py index bcee29dee149ff..2f3ccbcbe4c720 100644 --- a/tests/sentry/integrations/slack/actions/notification/test_slack_notify_service_action.py +++ b/tests/sentry/integrations/slack/actions/notification/test_slack_notify_service_action.py @@ -370,7 +370,7 @@ def test_after_noa_test_action( assert thread_ts_success.args[0] == EventLifecycleOutcome.SUCCESS @with_feature("organizations:workflow-engine-trigger-actions") - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") @patch("sentry.integrations.utils.metrics.EventLifecycle.record_event") @patch("sentry.integrations.slack.sdk_client.SlackSdkClient.chat_postMessage") @patch("slack_sdk.web.client.WebClient._perform_urllib_http_request") diff --git a/tests/sentry/integrations/slack/notifications/test_issue_alert.py b/tests/sentry/integrations/slack/notifications/test_issue_alert.py index d7eea5dd1285eb..065d8c7658fcda 100644 --- a/tests/sentry/integrations/slack/notifications/test_issue_alert.py +++ b/tests/sentry/integrations/slack/notifications/test_issue_alert.py @@ -273,7 +273,7 @@ def test_generic_issue_alert_user_block_workflow_engine_dual_write( return_value=TEST_ISSUE_OCCURRENCE, new_callable=mock.PropertyMock, ) - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_generic_issue_alert_user_block_workflow_engine_ui_links( self, occurrence: MagicMock ) -> None: diff --git a/tests/sentry/mail/test_adapter.py b/tests/sentry/mail/test_adapter.py index c7099541a64c8c..24da857d4709af 100644 --- a/tests/sentry/mail/test_adapter.py +++ b/tests/sentry/mail/test_adapter.py @@ -575,7 +575,7 @@ def test_notify_users_does_email(self, mock_logger, mock_func) -> None: @mock_notify @mock.patch("sentry.notifications.notifications.rules.logger") - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_notify_users_does_email_workflow_engine_ui_links(self, mock_logger, mock_func) -> None: self.create_user_option(user=self.user, key="timezone", value="Europe/Vienna") event_manager = EventManager({"message": "hello world", "level": "error"}) diff --git a/tests/sentry/notifications/notification_action/test_issue_alert_registry_handlers.py b/tests/sentry/notifications/notification_action/test_issue_alert_registry_handlers.py index b223e5628471d0..1dfdaf565f0109 100644 --- a/tests/sentry/notifications/notification_action/test_issue_alert_registry_handlers.py +++ b/tests/sentry/notifications/notification_action/test_issue_alert_registry_handlers.py @@ -169,7 +169,7 @@ def test_create_rule_instance_from_action(self) -> None: assert rule.status == ObjectStatus.ACTIVE assert rule.source == RuleSource.ISSUE - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_create_rule_instance_from_action_with_workflow_engine_ui_feature_flag(self) -> None: """Test that create_rule_instance_from_action creates a Rule with correct attributes""" rule = self.handler.create_rule_instance_from_action( @@ -222,7 +222,7 @@ def test_create_rule_instance_from_action_no_environment(self) -> None: assert rule.status == ObjectStatus.ACTIVE assert rule.source == RuleSource.ISSUE - @with_feature("organizations:workflow-engine-ui-links") + @with_feature("organizations:workflow-engine-ui") def test_create_rule_instance_from_action_no_environment_with_workflow_engine_ui_feature_flag( self, ): diff --git a/tests/sentry/workflow_engine/test_integration.py b/tests/sentry/workflow_engine/test_integration.py index 2771c11848455b..d08ed41668c04f 100644 --- a/tests/sentry/workflow_engine/test_integration.py +++ b/tests/sentry/workflow_engine/test_integration.py @@ -177,19 +177,6 @@ def test_workflow_engine__workflows__other_events(self) -> None: # We currently don't have a detector for this issue type, so it should not call workflow_engine. mock_process_workflow.assert_not_called() - def test_workflow_engine__workflows__no_flag(self) -> None: - self.create_event(self.project.id, datetime.utcnow(), str(self.detector.id)) - - assert self.group - - with mock.patch( - "sentry.workflow_engine.tasks.workflows.process_workflows_event.apply_async" - ) as mock_process_workflow: - self.call_post_process_group(self.group.id) - - # While this is the same test as the first one, it doesn't invoke the workflow engine because the feature flag is off. - mock_process_workflow.assert_not_called() - @mock.patch("sentry.workflow_engine.processors.action.trigger_action.apply_async") class TestWorkflowEngineIntegrationFromErrorPostProcess(BaseWorkflowIntegrationTest):