Skip to content

Commit 3b43a2c

Browse files
authored
chore(ACI): Add render_label method for sentry apps (#109123)
Follow up to #108419 and #108795 to add a `render_label` method for sentry app actions to be used by the backwards compatible issue alert serializer.
1 parent 3383c5e commit 3b43a2c

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

src/sentry/notifications/notification_action/issue_alert_registry/handlers/sentry_app_issue_alert_handler.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from dataclasses import asdict
22
from typing import Any
33

4+
from rest_framework import serializers
5+
46
from sentry.notifications.notification_action.registry import issue_alert_handler_registry
57
from sentry.notifications.notification_action.types import BaseIssueAlertHandler
68
from sentry.sentry_apps.services.app import app_service
9+
from sentry.sentry_apps.utils.errors import SentryAppError
710
from sentry.workflow_engine.models import Action
811
from sentry.workflow_engine.typings.notification_action import (
912
ActionFieldMapping,
@@ -12,6 +15,8 @@
1215
SentryAppFormConfigDataBlob,
1316
)
1417

18+
ValidationError = serializers.ValidationError
19+
1520

1621
@issue_alert_handler_registry.register(Action.Type.SENTRY_APP)
1722
class SentryAppIssueAlertHandler(BaseIssueAlertHandler):
@@ -74,3 +79,36 @@ def get_additional_fields(cls, action: Action, mapping: ActionFieldMapping) -> d
7479
settings = cls.process_settings(blob.settings)
7580
return {"settings": settings}
7681
return {}
82+
83+
@classmethod
84+
def render_label(cls, organization_id: int, blob: dict[str, Any]) -> str:
85+
"""
86+
blob: {
87+
'id': 'sentry.rules.actions.notify_event_sentry_app.NotifyEventSentryAppAction',
88+
'sentryAppInstallationUuid': 'str,
89+
}
90+
"""
91+
sentry_app_installation_uuid = blob.get("sentryAppInstallationUuid")
92+
93+
installations = app_service.get_many(
94+
filter=dict(uuids=[sentry_app_installation_uuid], organization_id=organization_id)
95+
)
96+
if not installations:
97+
raise SentryAppError(
98+
f"Sentry App installation with UUID {sentry_app_installation_uuid} not found."
99+
)
100+
101+
sentry_app = installations[0].sentry_app
102+
alert_rule_component = None
103+
for component in app_service.find_app_components(app_id=sentry_app.id):
104+
if component.type == "alert-rule-action":
105+
alert_rule_component = component
106+
break
107+
108+
if not alert_rule_component:
109+
raise ValidationError(
110+
f"Alert Actions are not enabled for the {sentry_app.name} integration."
111+
)
112+
113+
schema_title = alert_rule_component.app_schema.get("title")
114+
return schema_title if schema_title is not None else sentry_app.name

tests/sentry/api/serializers/test_rule.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import pytest
12
from django.db import DEFAULT_DB_ALIAS, connections
23
from django.test.utils import CaptureQueriesContext
34
from django.utils import timezone
5+
from rest_framework import serializers
46

57
from sentry.api.serializers import serialize
68
from sentry.api.serializers.models.rule import RuleSerializer, WorkflowEngineRuleSerializer
@@ -29,6 +31,8 @@
2931
from sentry.workflow_engine.models import WorkflowDataConditionGroup, WorkflowFireHistory
3032
from sentry.workflow_engine.models.data_condition import Condition
3133

34+
ValidationError = serializers.ValidationError
35+
3236

3337
@freeze_time()
3438
class RuleSerializerTest(TestCase):
@@ -628,3 +632,83 @@ def test_azure_devops_action(self) -> None:
628632
include_workflow_id=False,
629633
)
630634
self.assert_equal_serializers(rule)
635+
636+
def test_sentry_app_render_label(self) -> None:
637+
schema = {"elements": [self.create_alert_rule_action_schema()]}
638+
sentry_app = self.create_sentry_app(
639+
organization=self.organization,
640+
name="Test Application",
641+
is_alertable=True,
642+
schema=schema,
643+
)
644+
installation = self.create_sentry_app_installation(
645+
slug=sentry_app.slug, organization=self.organization
646+
)
647+
648+
action_data = {
649+
"id": "sentry.rules.actions.notify_event_sentry_app.NotifyEventSentryAppAction",
650+
"sentryAppInstallationUuid": installation.uuid,
651+
}
652+
rule = self.create_project_rule(
653+
project=self.project,
654+
action_data=[action_data],
655+
condition_data=self.conditions,
656+
include_legacy_rule_id=False,
657+
include_workflow_id=False,
658+
)
659+
self.assert_equal_serializers(rule)
660+
661+
def test_sentry_app_render_label_no_alert_rule_action_schema(self) -> None:
662+
schema = {"elements": [self.create_issue_link_schema()]}
663+
sentry_app = self.create_sentry_app(
664+
organization=self.organization,
665+
name="Test Application",
666+
is_alertable=True,
667+
schema=schema,
668+
)
669+
installation = self.create_sentry_app_installation(
670+
slug=sentry_app.slug, organization=self.organization
671+
)
672+
673+
action_data = {
674+
"id": "sentry.rules.actions.notify_event_sentry_app.NotifyEventSentryAppAction",
675+
"sentryAppInstallationUuid": installation.uuid,
676+
}
677+
rule = self.create_project_rule(
678+
project=self.project,
679+
action_data=[action_data],
680+
condition_data=self.conditions,
681+
include_legacy_rule_id=False,
682+
include_workflow_id=False,
683+
)
684+
with pytest.raises(ValidationError):
685+
self.assert_equal_serializers(rule)
686+
687+
def test_sentry_app_render_label_no_installation(self) -> None:
688+
schema = {"elements": [self.create_alert_rule_action_schema()]}
689+
sentry_app = self.create_sentry_app(
690+
organization=self.organization,
691+
name="Test Application",
692+
is_alertable=True,
693+
schema=schema,
694+
)
695+
installation = self.create_sentry_app_installation(
696+
slug=sentry_app.slug, organization=self.organization
697+
)
698+
699+
action_data = {
700+
"id": "sentry.rules.actions.notify_event_sentry_app.NotifyEventSentryAppAction",
701+
"sentryAppInstallationUuid": installation.uuid,
702+
}
703+
with assume_test_silo_mode(SiloMode.CONTROL):
704+
installation.delete()
705+
706+
rule = self.create_project_rule(
707+
project=self.project,
708+
action_data=[action_data],
709+
condition_data=self.conditions,
710+
include_legacy_rule_id=False,
711+
include_workflow_id=False,
712+
)
713+
# actions part of response are both []
714+
self.assert_equal_serializers(rule)

0 commit comments

Comments
 (0)