Browse Source

fix(slack): Fix button action generation for Slack block kit (#66935)

For the new Slack block kit, we have several usages of `MessageAction()`
that does not have the `label` parameter. In these instances, we
fallback to the `name` parameter.

For example, quota notifications for Slack. I've added the labels in
https://github.com/getsentry/getsentry/pull/13279.
Alberto Leal 1 year ago
parent
commit
a6467b0170

+ 3 - 2
src/sentry/integrations/slack/message_builder/base/block.py

@@ -86,10 +86,11 @@ class BlockSlackMessageBuilder(SlackMessageBuilder, ABC):
         return action
 
     @staticmethod
-    def get_button_action(action):
+    def get_button_action(action: MessageAction) -> SlackBlock:
+        button_text = action.label or action.name
         button = {
             "type": "button",
-            "text": {"type": "plain_text", "text": action.label},
+            "text": {"type": "plain_text", "text": button_text},
         }
         if action.value:
             button["action_id"] = action.value

+ 19 - 1
src/sentry/testutils/helpers/notifications.py

@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 import uuid
-from collections.abc import Mapping
+from collections.abc import Mapping, Sequence
 from datetime import UTC, datetime
 from typing import Any
 
@@ -17,6 +17,8 @@ from sentry.models.group import Group
 from sentry.models.team import Team
 from sentry.models.user import User
 from sentry.notifications.notifications.base import BaseNotification
+from sentry.notifications.utils.actions import MessageAction
+from sentry.services.hybrid_cloud.actor import RpcActor
 from sentry.services.hybrid_cloud.user import RpcUser
 from sentry.types.integrations import ExternalProviders
 
@@ -54,6 +56,22 @@ class DummyNotification(BaseNotification):
     def get_participants(self):
         return []
 
+    def get_message_actions(
+        self, recipient: RpcActor, provider: ExternalProviders
+    ) -> Sequence[MessageAction]:
+        zombo_link = MessageAction(
+            name="Go to Zombo.com",
+            style="primary",
+            url="http://zombo.com",
+        )
+        sentry_link = MessageAction(
+            name="Sentry Link",
+            label="Go to Sentry",
+            style="primary",
+            url="http://sentry.io",
+        )
+        return [zombo_link, sentry_link]
+
 
 class AnotherDummyNotification(DummyNotification):
     def __init__(self, organization, some_value) -> None:

+ 46 - 7
tests/sentry/integrations/slack/test_notifications.py

@@ -53,9 +53,12 @@ class SlackNotificationsTest(SlackActivityNotificationTest):
 
     @responses.activate
     def test_additional_attachment_block_kit(self):
-        with self.feature("organizations:slack-block-kit"), mock.patch.dict(
-            manager.attachment_generators,
-            {ExternalProviders.SLACK: additional_attachment_generator_block_kit},
+        with (
+            self.feature("organizations:slack-block-kit"),
+            mock.patch.dict(
+                manager.attachment_generators,
+                {ExternalProviders.SLACK: additional_attachment_generator_block_kit},
+            ),
         ):
             with self.tasks():
                 send_notification_as_slack(self.notification, [self.user], {}, {})
@@ -67,12 +70,30 @@ class SlackNotificationsTest(SlackActivityNotificationTest):
             assert data["text"][0] == "Notification Title"
 
             blocks = json.loads(data["blocks"][0])
-            assert len(blocks) == 4
+            assert len(blocks) == 5
 
             assert blocks[0]["text"]["text"] == "Notification Title"
             assert blocks[1]["text"]["text"] == "*My Title*  \n"
-            assert blocks[2]["text"]["text"] == self.organization.slug
-            assert blocks[3]["text"]["text"] == self.integration.id
+            # Message actions
+            assert blocks[2] == {
+                "elements": [
+                    {
+                        "text": {"text": "Go to Zombo.com", "type": "plain_text"},
+                        "type": "button",
+                        "url": "http://zombo.com",
+                        "value": "link_clicked",
+                    },
+                    {
+                        "text": {"text": "Go to Sentry", "type": "plain_text"},
+                        "type": "button",
+                        "url": "http://sentry.io",
+                        "value": "link_clicked",
+                    },
+                ],
+                "type": "actions",
+            }
+            assert blocks[3]["text"]["text"] == self.organization.slug
+            assert blocks[4]["text"]["text"] == self.integration.id
 
     @responses.activate
     def test_no_additional_attachment(self):
@@ -102,10 +123,28 @@ class SlackNotificationsTest(SlackActivityNotificationTest):
             assert data["text"][0] == "Notification Title"
 
             blocks = json.loads(data["blocks"][0])
-            assert len(blocks) == 2
+            assert len(blocks) == 3
 
             assert blocks[0]["text"]["text"] == "Notification Title"
             assert blocks[1]["text"]["text"] == "*My Title*  \n"
+            # Message actions
+            assert blocks[2] == {
+                "elements": [
+                    {
+                        "text": {"text": "Go to Zombo.com", "type": "plain_text"},
+                        "type": "button",
+                        "url": "http://zombo.com",
+                        "value": "link_clicked",
+                    },
+                    {
+                        "text": {"text": "Go to Sentry", "type": "plain_text"},
+                        "type": "button",
+                        "url": "http://sentry.io",
+                        "value": "link_clicked",
+                    },
+                ],
+                "type": "actions",
+            }
 
     @responses.activate
     @mock.patch("sentry.integrations.slack.notifications._get_attachments")