10
10
from django .utils .translation import gettext as _
11
11
from sentry_relay .processing import parse_release
12
12
13
- from sentry import tagstore
13
+ from sentry import features , tagstore
14
14
from sentry .api .endpoints .group_details import get_group_global_count
15
15
from sentry .constants import LOG_LEVELS_MAP
16
16
from sentry .eventstore .models import GroupEvent
22
22
format_actor_option ,
23
23
format_actor_options ,
24
24
get_color ,
25
+ get_timestamp ,
25
26
get_title_link ,
26
27
)
27
28
from sentry .integrations .slack .message_builder import (
@@ -264,20 +265,36 @@ def get_context(group: Group) -> str:
264
265
return context_text .rstrip ()
265
266
266
267
268
+ def get_option_groups (group : Group ) -> Sequence [Mapping [str , Any ]]:
269
+ all_members = group .project .get_members_as_rpc_users ()
270
+ members = list ({m .id : m for m in all_members }.values ())
271
+ teams = group .project .teams .all ()
272
+
273
+ option_groups = []
274
+ if teams :
275
+ option_groups .append ({"text" : "Teams" , "options" : format_actor_options (teams )})
276
+
277
+ if members :
278
+ option_groups .append ({"text" : "People" , "options" : format_actor_options (members )})
279
+
280
+ return option_groups
281
+
282
+
267
283
def get_option_groups_block_kit (group : Group ) -> Sequence [Mapping [str , Any ]]:
268
284
all_members = group .project .get_members_as_rpc_users ()
269
285
members = list ({m .id : m for m in all_members }.values ())
270
286
teams = group .project .teams .all ()
287
+ use_block_kit = features .has ("organizations:slack-block-kit" , group .project .organization )
271
288
272
289
option_groups = []
273
290
if teams :
274
- team_options = format_actor_options (teams , True )
291
+ team_options = format_actor_options (teams , use_block_kit )
275
292
option_groups .append (
276
293
{"label" : {"type" : "plain_text" , "text" : "Teams" }, "options" : team_options }
277
294
)
278
295
279
296
if members :
280
- member_options = format_actor_options (members , True )
297
+ member_options = format_actor_options (members , use_block_kit )
281
298
option_groups .append (
282
299
{"label" : {"type" : "plain_text" , "text" : "People" }, "options" : member_options }
283
300
)
@@ -408,51 +425,91 @@ def build_actions(
408
425
identity : RpcIdentity | None = None ,
409
426
) -> tuple [Sequence [MessageAction ], str , str ]:
410
427
"""Having actions means a button will be shown on the Slack message e.g. ignore, resolve, assign."""
428
+ use_block_kit = features .has ("organizations:slack-block-kit" , project .organization )
429
+
411
430
if actions and identity :
412
431
text = get_action_text (text , actions , identity )
413
432
return [], text , "_actioned_issue"
414
433
415
434
status = group .get_status ()
416
435
417
- def _ignore_button () -> MessageAction | None :
436
+ def _ignore_button (use_block_kit ) -> MessageAction | None :
418
437
if group .issue_category == GroupCategory .FEEDBACK :
419
438
return None
439
+ if use_block_kit :
440
+ if status == GroupStatus .IGNORED :
441
+ return MessageAction (
442
+ name = "status" , label = "Mark as Ongoing" , value = "unresolved:ongoing"
443
+ )
444
+ return MessageAction (name = "status" , label = "Archive" , value = "archive_dialog" )
445
+
420
446
if status == GroupStatus .IGNORED :
421
- return MessageAction (name = "status" , label = "Mark as Ongoing" , value = "unresolved:ongoing" )
447
+ return MessageAction (
448
+ name = "status" ,
449
+ label = "Mark as Ongoing" ,
450
+ value = "unresolved:ongoing" ,
451
+ )
422
452
423
- return MessageAction (name = "status" , label = "Archive" , value = "archive_dialog" )
453
+ return MessageAction (
454
+ name = "status" ,
455
+ label = "Archive" ,
456
+ value = "ignored:until_escalating" ,
457
+ )
458
+
459
+ def _resolve_button (use_block_kit ) -> MessageAction :
460
+ if use_block_kit :
461
+ if status == GroupStatus .RESOLVED :
462
+ return MessageAction (
463
+ name = "unresolved:ongoing" , label = "Unresolve" , value = "unresolved:ongoing"
464
+ )
465
+ if not project .flags .has_releases :
466
+ return MessageAction (name = "status" , label = "Resolve" , value = "resolved" )
467
+ return MessageAction (
468
+ name = "status" ,
469
+ label = "Resolve" ,
470
+ value = "resolve_dialog" ,
471
+ )
424
472
425
- def _resolve_button () -> MessageAction :
426
473
if status == GroupStatus .RESOLVED :
427
474
return MessageAction (
428
- name = "unresolved:ongoing" , label = "Unresolve" , value = "unresolved:ongoing"
475
+ name = "status" ,
476
+ label = "Unresolve" ,
477
+ value = "unresolved:ongoing" ,
429
478
)
430
- if not project .flags .has_releases :
431
- return MessageAction (name = "status" , label = "Resolve" , value = "resolved" )
432
479
480
+ if not project .flags .has_releases :
481
+ return MessageAction (
482
+ name = "status" ,
483
+ label = "Resolve" ,
484
+ value = "resolved" ,
485
+ )
433
486
return MessageAction (
434
- name = "status " ,
435
- label = "Resolve" ,
487
+ name = "resolve_dialog " ,
488
+ label = "Resolve... " ,
436
489
value = "resolve_dialog" ,
437
490
)
438
491
439
- def _assign_button () -> MessageAction :
492
+ def _assign_button (use_block_kit ) -> MessageAction :
440
493
assignee = group .get_assignee ()
441
494
assign_button = MessageAction (
442
495
name = "assign" ,
443
496
label = "Select Assignee..." ,
444
497
type = "select" ,
445
- selected_options = format_actor_options ([assignee ], True ) if assignee else [],
446
- option_groups = get_option_groups_block_kit (group ),
498
+ selected_options = format_actor_options ([assignee ]) if assignee else [],
499
+ option_groups = (
500
+ get_option_groups (group )
501
+ if not use_block_kit
502
+ else get_option_groups_block_kit (group )
503
+ ),
447
504
)
448
505
return assign_button
449
506
450
507
action_list = [
451
508
a
452
509
for a in [
453
- _resolve_button (),
454
- _ignore_button (),
455
- _assign_button (),
510
+ _resolve_button (use_block_kit ),
511
+ _ignore_button (use_block_kit ),
512
+ _assign_button (use_block_kit ),
456
513
]
457
514
if a is not None
458
515
]
@@ -495,6 +552,9 @@ def __init__(
495
552
self .skip_fallback = skip_fallback
496
553
self .notes = notes
497
554
self .commits = commits
555
+ self .use_block_kit = features .has (
556
+ "organizations:slack-block-kit" , group .project .organization
557
+ )
498
558
499
559
@property
500
560
def escape_text (self ) -> bool :
@@ -508,7 +568,14 @@ def build(self, notification_uuid: str | None = None) -> SlackBlock | SlackAttac
508
568
text = build_attachment_text (self .group , self .event ) or ""
509
569
text = text .strip (" \n " )
510
570
511
- text = escape_slack_markdown_text (text )
571
+ if self .use_block_kit :
572
+ text = escape_slack_markdown_text (text )
573
+ if not self .use_block_kit and self .escape_text :
574
+ text = escape_slack_text (text )
575
+ # XXX(scefali): Not sure why we actually need to do this just for unfurled messages.
576
+ # If we figure out why this is required we should note it here because it's quite strange
577
+ if self .is_unfurl :
578
+ text = escape_slack_text (text )
512
579
513
580
# This link does not contain user input (it's a static label and a url), must not escape it.
514
581
replay_link = build_attachment_replay_link (self .group , self .event )
@@ -517,6 +584,7 @@ def build(self, notification_uuid: str | None = None) -> SlackBlock | SlackAttac
517
584
# If an event is unspecified, use the tags of the latest event (if one exists).
518
585
event_for_tags = self .event or self .group .get_latest_event ()
519
586
color = get_color (event_for_tags , self .notification , self .group )
587
+ fields = build_tag_fields (event_for_tags , self .tags )
520
588
footer = (
521
589
self .notification .build_notification_footer (self .recipient , ExternalProviders .SLACK )
522
590
if self .notification and self .recipient
@@ -550,6 +618,25 @@ def build(self, notification_uuid: str | None = None) -> SlackBlock | SlackAttac
550
618
)
551
619
title = build_attachment_title (obj )
552
620
621
+ if not features .has ("organizations:slack-block-kit" , self .group .project .organization ):
622
+ if replay_link :
623
+ text += f"\n \n { replay_link } "
624
+ if action_text and self .identity :
625
+ text += "\n " + action_text
626
+
627
+ return self ._build (
628
+ actions = payload_actions ,
629
+ callback_id = json .dumps ({"issue" : self .group .id }),
630
+ color = color ,
631
+ fallback = self .build_fallback_text (obj , project .slug ),
632
+ fields = fields ,
633
+ footer = footer ,
634
+ text = text ,
635
+ title = title ,
636
+ title_link = title_link ,
637
+ ts = get_timestamp (self .group , self .event ) if not self .issue_details else None ,
638
+ )
639
+
553
640
# build up the blocks for newer issue alert formatting #
554
641
555
642
# build title block
0 commit comments