diff --git a/src/sentry/integrations/discord/message_builder/issues.py b/src/sentry/integrations/discord/message_builder/issues.py index 10f8601fae07fc..be25e6fd7d050f 100644 --- a/src/sentry/integrations/discord/message_builder/issues.py +++ b/src/sentry/integrations/discord/message_builder/issues.py @@ -1,6 +1,6 @@ from __future__ import annotations -from sentry import features, tagstore +from sentry import tagstore from sentry.integrations.discord.message_builder import LEVEL_TO_COLOR from sentry.integrations.discord.message_builder.base.base import ( DiscordMessage, @@ -24,9 +24,8 @@ from sentry.models.group import Group, GroupStatus from sentry.models.project import Project from sentry.models.rule import Rule -from sentry.notifications.notification_action.utils import should_fire_workflow_actions from sentry.notifications.notifications.base import ProjectNotification -from sentry.notifications.utils.rules import get_key_from_rule_data +from sentry.notifications.utils.rules import RuleIdType, get_rule_or_workflow_id from sentry.services.eventstore.models import GroupEvent from ..message_builder.base.component import DiscordComponentCustomIds as CustomIds @@ -60,41 +59,37 @@ def build(self, notification_uuid: str | None = None) -> DiscordMessage: obj: Group | GroupEvent = self.event if self.event is not None else self.group rule_id = None rule_environment_id = None + key: RuleIdType = "legacy_rule_id" if self.rules: rule_environment_id = self.rules[0].environment_id - if features.has("organizations:workflow-engine-ui-links", 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")) - else: - rule_id = self.rules[0].id + key, rule_id = get_rule_or_workflow_id(self.rules[0]) url = None - - if features.has("organizations:workflow-engine-ui-links", self.group.organization): - url = get_title_link_workflow_engine_ui( - self.group, - self.event, - self.link_to_event, - self.issue_details, - self.notification, - ExternalProviders.DISCORD, - rule_id, - rule_environment_id, - notification_uuid=notification_uuid, - ) - else: - url = get_title_link( - self.group, - self.event, - self.link_to_event, - self.issue_details, - self.notification, - ExternalProviders.DISCORD, - rule_id, - rule_environment_id, - notification_uuid=notification_uuid, - ) + match key: + case "workflow_id": + url = get_title_link_workflow_engine_ui( + self.group, + self.event, + self.link_to_event, + self.issue_details, + self.notification, + ExternalProviders.DISCORD, + int(rule_id) if rule_id else None, + rule_environment_id, + notification_uuid=notification_uuid, + ) + case "legacy_rule_id": + url = get_title_link( + self.group, + self.event, + self.link_to_event, + self.issue_details, + self.notification, + ExternalProviders.DISCORD, + int(rule_id) if rule_id else None, + rule_environment_id, + notification_uuid=notification_uuid, + ) embeds = [ DiscordMessageEmbed( diff --git a/src/sentry/integrations/messaging/message_builder.py b/src/sentry/integrations/messaging/message_builder.py index 5d21043ae43111..cbae97e4008afc 100644 --- a/src/sentry/integrations/messaging/message_builder.py +++ b/src/sentry/integrations/messaging/message_builder.py @@ -15,7 +15,7 @@ from sentry.notifications.notifications.base import BaseNotification from sentry.notifications.notifications.rules import AlertRuleNotification from sentry.notifications.utils.links import create_link_to_workflow -from sentry.notifications.utils.rules import get_key_from_rule_data +from sentry.notifications.utils.rules import get_key_from_rule_data, get_rule_or_workflow_id from sentry.services.eventstore.models import Event, GroupEvent from sentry.users.services.user import RpcUser from sentry.utils.http import absolute_uri @@ -291,14 +291,12 @@ def build_footer( ) -> str: footer = f"{group.qualified_short_id}" if rules: - if features.has("organizations:workflow-engine-ui-links", group.organization): - rule_url = absolute_uri( - create_link_to_workflow( - group.organization.id, get_key_from_rule_data(rules[0], "workflow_id") - ) - ) - else: - rule_url = build_rule_url(rules[0], group, project) + key, value = get_rule_or_workflow_id(rules[0]) + match key: + case "workflow_id": + rule_url = absolute_uri(create_link_to_workflow(group.organization.id, value)) + case "legacy_rule_id": + rule_url = build_rule_url(rules[0], group, project) # If this notification is triggered via the "Send Test Notification" # button then the label is not defined, but the url works. diff --git a/src/sentry/integrations/opsgenie/client.py b/src/sentry/integrations/opsgenie/client.py index bb2c16c462ff62..b6e1474dc0e42f 100644 --- a/src/sentry/integrations/opsgenie/client.py +++ b/src/sentry/integrations/opsgenie/client.py @@ -2,7 +2,6 @@ from typing import Literal -from sentry import features from sentry.integrations.client import ApiClient from sentry.integrations.models.integration import Integration from sentry.integrations.on_call.metrics import OnCallInteractionType @@ -12,7 +11,7 @@ from sentry.models.group import Group from sentry.notifications.notification_action.utils import should_fire_workflow_actions from sentry.notifications.utils.links import create_link_to_workflow -from sentry.notifications.utils.rules import get_key_from_rule_data +from sentry.notifications.utils.rules import get_key_from_rule_data, split_rules_by_rule_workflow_id from sentry.services.eventstore.models import Event, GroupEvent from sentry.shared_integrations.exceptions import ApiError @@ -91,19 +90,30 @@ def build_issue_alert_payload( group_params = {"referrer": IntegrationProviderSlug.OPSGENIE.value} if notification_uuid: group_params["notification_uuid"] = notification_uuid + + rules_and_workflows = split_rules_by_rule_workflow_id(rules) + workflow_urls = self._get_workflow_urls(group, rules_and_workflows.workflow_rules) + rule_urls = self._get_rule_urls(group, rules_and_workflows.rules) rule_workflow_context = {} - if features.has("organizations:workflow-engine-ui-links", group.project.organization): - workflow_urls = self._get_workflow_urls(group, rules) - rule_workflow_context = { - "Triggering Workflows": ", ".join([rule.label for rule in rules]), - "Triggering Workflow URLs": "\n".join(workflow_urls), - } - else: - rule_urls = self._get_rule_urls(group, rules) - rule_workflow_context = { - "Triggering Rules": ", ".join([rule.label for rule in rules]), - "Triggering Rule URLs": "\n".join(rule_urls), - } + if rule_urls: + rule_workflow_context.update( + { + "Triggering Rules": ", ".join( + [rule.label for rule in rules_and_workflows.rules] + ), + "Triggering Rule URLs": "\n".join(rule_urls), + } + ) + if workflow_urls: + rule_workflow_context.update( + { + "Triggering Workflows": ", ".join( + [workflow.label for workflow in rules_and_workflows.workflow_rules] + ), + "Triggering Workflow URLs": "\n".join(workflow_urls), + } + ) + payload["details"] = { "Sentry ID": str(group.id), "Sentry Group": getattr(group, "title", group.message).encode("utf-8"), diff --git a/src/sentry/integrations/slack/message_builder/issues.py b/src/sentry/integrations/slack/message_builder/issues.py index adae703f42cb76..2db986f00ef2df 100644 --- a/src/sentry/integrations/slack/message_builder/issues.py +++ b/src/sentry/integrations/slack/message_builder/issues.py @@ -55,7 +55,6 @@ from sentry.models.repository import Repository from sentry.models.rule import Rule from sentry.models.team import Team -from sentry.notifications.notification_action.utils import should_fire_workflow_actions from sentry.notifications.notifications.base import ProjectNotification from sentry.notifications.platform.slack.renderers.seer import SeerSlackRenderer from sentry.notifications.platform.templates.seer import SeerAutofixTrigger @@ -64,7 +63,7 @@ dedupe_suggested_assignees, get_suspect_commit_users, ) -from sentry.notifications.utils.rules import get_key_from_rule_data +from sentry.notifications.utils.rules import get_rule_or_workflow_id from sentry.services.eventstore.models import Event, GroupEvent from sentry.snuba.referrer import Referrer from sentry.types.actor import Actor @@ -669,18 +668,18 @@ def build(self, notification_uuid: str | None = None) -> SlackBlock: rule_id = None rule_environment_id = None + key = "legacy_rule_id" if self.rules: - if features.has("organizations:workflow-engine-ui-links", self.group.organization): - rule_id = int(get_key_from_rule_data(self.rules[0], "workflow_id")) - workflow = Workflow.objects.filter(id=rule_id).first() - rule_environment_id = workflow.environment_id if workflow else None - 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")) - rule = Rule.objects.filter(id=rule_id).first() - rule_environment_id = rule.environment_id if rule else None - else: - rule_id = self.rules[0].id - rule_environment_id = self.rules[0].environment_id + key, value = get_rule_or_workflow_id(self.rules[0]) + rule_id = int(value) + + match key: + case "workflow_id": + workflow = Workflow.objects.filter(id=rule_id).first() + rule_environment_id = workflow.environment_id if workflow else None + case "legacy_rule_id": + rule = Rule.objects.filter(id=rule_id).first() + rule_environment_id = rule.environment_id if rule else None # build up actions text if self.actions and self.identity and not action_text: @@ -689,30 +688,31 @@ 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): - title_link = get_title_link_workflow_engine_ui( - self.group, - self.event, - self.link_to_event, - self.issue_details, - self.notification, - ExternalProviders.SLACK, - rule_id, - rule_environment_id, - notification_uuid=notification_uuid, - ) - else: - title_link = get_title_link( - self.group, - self.event, - self.link_to_event, - self.issue_details, - self.notification, - ExternalProviders.SLACK, - rule_id, - rule_environment_id, - notification_uuid=notification_uuid, - ) + match key: + case "workflow_id": + title_link = get_title_link_workflow_engine_ui( + self.group, + self.event, + self.link_to_event, + self.issue_details, + self.notification, + ExternalProviders.SLACK, + rule_id, + rule_environment_id, + notification_uuid=notification_uuid, + ) + case "legacy_rule_id": + title_link = get_title_link( + self.group, + self.event, + self.link_to_event, + self.issue_details, + self.notification, + ExternalProviders.SLACK, + rule_id, + rule_environment_id, + notification_uuid=notification_uuid, + ) blocks = [self.get_title_block(event_or_group, has_action, title_link)] diff --git a/src/sentry/integrations/slack/message_builder/util.py b/src/sentry/integrations/slack/message_builder/util.py index 5e8c313568d8f1..dd150c02a7fe87 100644 --- a/src/sentry/integrations/slack/message_builder/util.py +++ b/src/sentry/integrations/slack/message_builder/util.py @@ -1,13 +1,12 @@ from collections.abc import Sequence -from sentry import features from sentry.integrations.messaging.message_builder import build_rule_url from sentry.integrations.slack.message_builder.types import SLACK_URL_FORMAT from sentry.models.group import Group from sentry.models.project import Project from sentry.models.rule import Rule from sentry.notifications.utils.links import create_link_to_workflow -from sentry.notifications.utils.rules import get_key_from_rule_data +from sentry.notifications.utils.rules import get_rule_or_workflow_id from sentry.utils.http import absolute_uri @@ -19,14 +18,12 @@ def build_slack_footer( footer = f"{group.qualified_short_id}" if rules: - if features.has("organizations:workflow-engine-ui-links", group.organization): - rule_url = absolute_uri( - create_link_to_workflow( - group.organization.id, get_key_from_rule_data(rules[0], "workflow_id") - ) - ) - else: - rule_url = build_rule_url(rules[0], group, project) + key, value = get_rule_or_workflow_id(rules[0]) + match key: + case "workflow_id": + rule_url = absolute_uri(create_link_to_workflow(group.organization.id, value)) + case "legacy_rule_id": + rule_url = build_rule_url(rules[0], group, project) # If this notification is triggered via the "Send Test Notification" # button then the label is not defined, but the url works. text = rules[0].label if rules[0].label else "Test Alert" diff --git a/src/sentry/notifications/notifications/rules.py b/src/sentry/notifications/notifications/rules.py index d46dc9f8ae5ce9..afb18bb62a0fcf 100644 --- a/src/sentry/notifications/notifications/rules.py +++ b/src/sentry/notifications/notifications/rules.py @@ -298,15 +298,13 @@ def get_notification_title( title_str = "Alert triggered" if self.rules: - rule_url = build_rule_url(self.rules[0], self.group, self.project) - key = "legacy_rule_id" - try: - key, value = get_rule_or_workflow_id(self.rules[0]) - except AssertionError: - pass + key, value = get_rule_or_workflow_id(self.rules[0]) - if key == "workflow_id": - rule_url = absolute_uri(create_link_to_workflow(self.organization.id, value)) + match key: + case "workflow_id": + rule_url = absolute_uri(create_link_to_workflow(self.organization.id, value)) + case "legacy_rule_id": + rule_url = build_rule_url(self.rules[0], self.group, self.project) title_str += ( f" {self.format_url(text=self.rules[0].label, url=rule_url, provider=provider)}" diff --git a/src/sentry/notifications/utils/rules.py b/src/sentry/notifications/utils/rules.py index 438802324dd3e9..05b3dfa1278448 100644 --- a/src/sentry/notifications/utils/rules.py +++ b/src/sentry/notifications/utils/rules.py @@ -1,8 +1,11 @@ from collections.abc import Sequence from dataclasses import dataclass +from typing import Literal from sentry.models.rule import Rule +RuleIdType = Literal["workflow_id", "legacy_rule_id"] + def get_key_from_rule_data(rule: Rule, key: str) -> str: value = rule.data.get("actions", [{}])[0].get(key) @@ -20,19 +23,22 @@ def split_rules_by_rule_workflow_id(rules: Sequence[Rule]) -> RulesAndWorkflows: parsed_rules = [] workflow_rules = [] for rule in rules: - try: - key, _ = get_rule_or_workflow_id(rule) - if key == "workflow_id": + key, _ = get_rule_or_workflow_id(rule) + match key: + case "workflow_id": workflow_rules.append(rule) - else: + case "legacy_rule_id": parsed_rules.append(rule) - except AssertionError: - parsed_rules.append(rule) return RulesAndWorkflows(rules=parsed_rules, workflow_rules=workflow_rules) -def get_rule_or_workflow_id(rule: Rule) -> tuple[str, str]: +def get_rule_or_workflow_id(rule: Rule) -> tuple[RuleIdType, str]: try: return ("legacy_rule_id", get_key_from_rule_data(rule, "legacy_rule_id")) except AssertionError: + pass + + try: return ("workflow_id", get_key_from_rule_data(rule, "workflow_id")) + except AssertionError: + return ("legacy_rule_id", str(rule.id)) diff --git a/src/sentry/rules/actions/integrations/create_ticket/utils.py b/src/sentry/rules/actions/integrations/create_ticket/utils.py index af0b1b78029c88..91dd3c356f3675 100644 --- a/src/sentry/rules/actions/integrations/create_ticket/utils.py +++ b/src/sentry/rules/actions/integrations/create_ticket/utils.py @@ -5,7 +5,6 @@ from rest_framework.response import Response -from sentry import features from sentry.constants import ObjectStatus from sentry.exceptions import InvalidIdentity from sentry.integrations.base import IntegrationInstallation @@ -143,9 +142,9 @@ 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): - workflow_id = data.get("workflow_id") - assert workflow_id is not None + + workflow_id = data.get("workflow_id") + if workflow_id is not None: data["description"] = build_description_workflow_engine_ui( event, workflow_id, installation, generate_footer ) diff --git a/src/sentry/sentry_apps/tasks/sentry_apps.py b/src/sentry/sentry_apps/tasks/sentry_apps.py index a3c86e027a6e0e..a7b91a659e6855 100644 --- a/src/sentry/sentry_apps/tasks/sentry_apps.py +++ b/src/sentry/sentry_apps/tasks/sentry_apps.py @@ -11,7 +11,7 @@ from requests import HTTPError, Timeout from requests.exceptions import ChunkedEncodingError, ConnectionError, RequestException -from sentry import analytics, features, nodestore +from sentry import analytics, nodestore from sentry.analytics.events.alert_rule_ui_component_webhook_sent import ( AlertRuleUiComponentWebhookSentEvent, ) @@ -40,7 +40,7 @@ from sentry.models.organization import Organization from sentry.models.organizationmapping import OrganizationMapping from sentry.models.project import Project -from sentry.notifications.utils.rules import get_key_from_rule_data +from sentry.notifications.utils.rules import get_rule_or_workflow_id from sentry.sentry_apps.api.serializers.app_platform_event import AppPlatformEvent from sentry.sentry_apps.metrics import ( SentryAppEventType, @@ -720,8 +720,6 @@ def send_resource_change_webhook( def notify_sentry_app(event: GroupEvent, futures: Sequence[RuleFuture]): - from sentry.notifications.notification_action.utils import should_fire_workflow_actions - for f in futures: if not f.kwargs.get("sentry_app"): logger.info( @@ -742,16 +740,13 @@ 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): - 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") + _, id = get_rule_or_workflow_id(f.rule) settings = f.kwargs.get("schema_defined_settings") if settings: extra_kwargs["additional_payload_key"] = "issue_alert" extra_kwargs["additional_payload"] = { - "id": id, + "id": int(id), "title": f.rule.label, "sentry_app_id": f.kwargs["sentry_app"].id, "settings": settings, diff --git a/tests/sentry/sentry_apps/tasks/test_sentry_apps.py b/tests/sentry/sentry_apps/tasks/test_sentry_apps.py index fe0f7b0db376b3..92b49937a3c705 100644 --- a/tests/sentry/sentry_apps/tasks/test_sentry_apps.py +++ b/tests/sentry/sentry_apps/tasks/test_sentry_apps.py @@ -380,7 +380,7 @@ def test_send_alert_event_with_additional_payload_legacy_rule_id( assert payload["data"]["triggered_rule"] == rule.label assert payload["data"]["issue_alert"] == { # Use the legacy rule id - "id": "123", + "id": 123, "title": rule.label, "sentry_app_id": self.sentry_app.id, "settings": settings,