def build_group_attachment( group: Group, event=None, tags: Mapping[str, str] = None, identity: Identity = None, actions=None, rules: List[Rule] = None, link_to_event: bool = False, ): # XXX(dcramer): options are limited to 100 choices, even when nested status = group.get_status() members = get_member_assignees(group) teams = get_team_assignees(group) logo_url = absolute_uri(get_asset_url("sentry", "images/sentry-email-avatar.png")) text = build_attachment_text(group, event) or "" if actions is None: actions = [] assignee = get_assignee(group) resolve_button = { "name": "resolve_dialog", "value": "resolve_dialog", "type": "button", "text": "Resolve...", } ignore_button = {"name": "status", "value": "ignored", "type": "button", "text": "Ignore"} project = Project.objects.get_from_cache(id=group.project_id) cache_key = "has_releases:2:%s" % (project.id) has_releases = cache.get(cache_key) if has_releases is None: has_releases = ReleaseProject.objects.filter(project_id=project.id).exists() if has_releases: cache.set(cache_key, True, 3600) else: cache.set(cache_key, False, 60) if not has_releases: resolve_button.update({"name": "status", "text": "Resolve", "value": "resolved"}) if status == GroupStatus.RESOLVED: resolve_button.update({"name": "status", "text": "Unresolve", "value": "unresolved"}) if status == GroupStatus.IGNORED: ignore_button.update({"text": "Stop Ignoring", "value": "unresolved"}) option_groups = [] if teams: option_groups.append({"text": "Teams", "options": teams}) if members: option_groups.append({"text": "People", "options": members}) payload_actions = [ resolve_button, ignore_button, { "name": "assign", "text": "Select Assignee...", "type": "select", "selected_options": [assignee], "option_groups": option_groups, }, ] # If an event is unspecified, use the tags of the latest event (if one exists). event_for_tags = event if event else group.get_latest_event() fallback_color = LEVEL_TO_COLOR["error"] color = ( LEVEL_TO_COLOR.get(event_for_tags.get_tag("level"), fallback_color) if event_for_tags else fallback_color ) fields = [] if tags: event_tags = event_for_tags.tags if event_for_tags else [] for key, value in event_tags: std_key = tagstore.get_standardized_key(key) if std_key not in tags: continue labeled_value = tagstore.get_tag_value_label(key, value) fields.append( { "title": std_key.encode("utf-8"), "value": labeled_value.encode("utf-8"), "short": True, } ) if actions: action_texts = [_f for _f in [build_action_text(group, identity, a) for a in actions] if _f] text += "\n" + "\n".join(action_texts) color = ACTIONED_ISSUE_COLOR payload_actions = [] ts = group.last_seen if event: event_ts = event.datetime ts = max(ts, event_ts) footer = f"{group.qualified_short_id}" if rules: rule_url = build_rule_url(rules[0], group, project) footer += f" via <{rule_url}|{rules[0].label}>" if len(rules) > 1: footer += f" (+{len(rules) - 1} other)" obj = event if event is not None else group if event and link_to_event: title_link = group.get_absolute_url(params={"referrer": "slack"}, event_id=event.event_id) else: title_link = group.get_absolute_url(params={"referrer": "slack"}) return { "fallback": f"[{project.slug}] {obj.title}", "title": build_attachment_title(obj), "title_link": title_link, "text": text, "fields": fields, "mrkdwn_in": ["text"], "callback_id": json.dumps({"issue": group.id}), "footer_icon": logo_url, "footer": footer, "ts": to_timestamp(ts), "color": color, "actions": payload_actions, }
def build_group_attachment( group: Group, event=None, tags: Mapping[str, str] = None, identity: Identity = None, actions=None, rules: List[Rule] = None, link_to_event: bool = False, issue_alert: bool = False, ): # XXX(dcramer): options are limited to 100 choices, even when nested logo_url = absolute_uri( get_asset_url("sentry", "images/sentry-email-avatar.png")) text = build_attachment_text(group, event) or "" project = Project.objects.get_from_cache(id=group.project_id) # If an event is unspecified, use the tags of the latest event (if one exists). event_for_tags = event if event else group.get_latest_event() fallback_color = LEVEL_TO_COLOR["error"] color = (LEVEL_TO_COLOR.get(event_for_tags.get_tag("level"), fallback_color) if event_for_tags else fallback_color) fields = build_tag_fields(event_for_tags, tags) ts = group.last_seen if event: event_ts = event.datetime ts = max(ts, event_ts) footer = build_footer(group, issue_alert, project, rules) obj = event if event is not None else group if event and link_to_event: title_link = group.get_absolute_url(params={"referrer": "slack"}, event_id=event.event_id) elif issue_alert: title_link = group.get_absolute_url( params={"referrer": "IssueAlertSlack"}) else: title_link = group.get_absolute_url(params={"referrer": "slack"}) if not issue_alert: payload_actions, text, color = build_actions(group, project, text, color, actions, identity) else: payload_actions = [] return { "fallback": f"[{project.slug}] {obj.title}", "title": build_attachment_title(obj), "title_link": title_link, "text": text, "fields": fields, "mrkdwn_in": ["text"], "callback_id": json.dumps({"issue": group.id}), "footer_icon": logo_url, "footer": footer, "ts": to_timestamp(ts), "color": color, "actions": payload_actions, }