Show incident button first when alert group is acknowledged (#4642)

# What this PR does

* Move declare incident button to first position when incident is
acknowledged
* Move resolved text above buttons, so buttons remain on the same place
when clicked
<img width="549" alt="Screenshot 2024-07-09 at 11 52 33 PM"
src="https://github.com/grafana/oncall/assets/2262529/68cfb42f-c7ad-42b9-8404-e3400eb70332">
<img width="529" alt="Screenshot 2024-07-09 at 11 52 41 PM"
src="https://github.com/grafana/oncall/assets/2262529/d8e36dec-ddfc-4db6-9918-0fb478c1462f">


## Which issue(s) this PR closes

Closes https://github.com/grafana/oncall/issues/1908

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.

---------

Co-authored-by: Joey Orlando <joseph.t.orlando@gmail.com>
Co-authored-by: Joey Orlando <joey.orlando@grafana.com>
This commit is contained in:
Ildar Iskhakov 2024-07-10 23:01:01 +08:00 committed by GitHub
parent d3c1611d23
commit 993725d2ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 132 additions and 172 deletions

View file

@ -91,19 +91,22 @@ class AlertGroupSlackRenderer(AlertGroupBaseRenderer):
def render_alert_group_attachments(self):
attachments = self.alert_renderer.render_alert_attachments()
alert_group = self.alert_group
root_alert_group = alert_group.root_alert_group
if root_alert_group is not None:
slack_message = root_alert_group.slack_message
root_ag_name = root_alert_group.long_verbose_name_without_formatting
if self.alert_group.root_alert_group is not None:
slack_message = self.alert_group.root_alert_group.slack_message
root_ag_name = self.alert_group.root_alert_group.long_verbose_name_without_formatting
if slack_message:
footer_text = f"Attached to *<{slack_message.permalink}|{root_ag_name}>*"
else:
footer_text = (f"Attached to *{root_ag_name}*",)
attachments.extend(
[
{
"fallback": "Subscription...",
"footer": footer_text,
"footer": (
f"Attached to *<{slack_message.permalink}|{root_ag_name}>*"
if slack_message
else f"Attached to *{root_ag_name}*"
),
"color": "danger",
"mrkdwn": True,
"callback_id": "subscription notification",
@ -118,42 +121,44 @@ class AlertGroupSlackRenderer(AlertGroupBaseRenderer):
}
]
)
if self.alert_group.root_alert_group.acknowledged:
if root_alert_group.acknowledged:
attachments[0]["color"] = "warning"
if self.alert_group.root_alert_group.resolved:
if root_alert_group.resolved:
attachments[0]["color"] = "good"
attachments[0]["actions"] = []
return attachments
# Attaching resolve information
if alert_group.resolved:
attachments.append(
{
"fallback": "Resolved...",
"text": alert_group.get_resolve_text(mention_user=False),
"callback_id": "alert",
}
)
elif alert_group.acknowledged:
attachments.append(
{
"fallback": "Acknowledged...",
"text": alert_group.get_acknowledge_text(mention_user=False),
"callback_id": "alert",
}
)
# Attaching buttons
if self.alert_group.wiped_at is None:
if alert_group.wiped_at is None:
attachment_alert_buttons = self._get_buttons_attachments()
if len(attachment_alert_buttons["blocks"][0]["elements"]) > 0:
attachments.append(attachment_alert_buttons)
# Attaching resolve information
if self.alert_group.resolved:
resolve_attachment = {
"fallback": "Resolved...",
"text": self.alert_group.get_resolve_text(mention_user=False),
"callback_id": "alert",
}
attachments.append(resolve_attachment)
else:
if self.alert_group.acknowledged:
ack_attachment = {
"fallback": "Acknowledged...",
"text": self.alert_group.get_acknowledge_text(mention_user=False),
"callback_id": "alert",
}
attachments.append(ack_attachment)
# Attaching invitation info
if not self.alert_group.resolved:
if not alert_group.resolved:
attachments += self._get_invitation_attachment()
attachments = self._set_attachments_color(attachments)
return attachments
return self._set_attachments_color(attachments)
def _set_attachments_color(self, attachments):
color = "#a30200" # danger
@ -174,155 +179,110 @@ class AlertGroupSlackRenderer(AlertGroupBaseRenderer):
def _get_buttons_blocks(self):
from apps.alerts.models import AlertGroup
buttons = []
if not self.alert_group.is_maintenance_incident:
if not self.alert_group.resolved:
if not self.alert_group.acknowledged:
buttons.append(
{
"text": {
"type": "plain_text",
"text": "Acknowledge",
"emoji": True,
},
"type": "button",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step(
"distribute_alerts",
"AcknowledgeGroupStep",
).routing_uid(),
},
)
else:
buttons.append(
{
"text": {
"type": "plain_text",
"text": "Unacknowledge",
"emoji": True,
},
"type": "button",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step(
"distribute_alerts",
"UnAcknowledgeGroupStep",
).routing_uid(),
},
)
buttons.append(
{
"text": {"type": "plain_text", "text": "Resolve", "emoji": True},
"type": "button",
"style": "primary",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step("distribute_alerts", "ResolveGroupStep").routing_uid(),
},
)
alert_group = self.alert_group
integration = alert_group.channel
grafana_incident_enabled = integration.organization.is_grafana_incident_enabled
if not self.alert_group.silenced:
silence_options = [
{
"text": {"type": "plain_text", "text": text, "emoji": True},
"value": self._alert_group_action_value(delay=value),
}
for value, text in AlertGroup.SILENCE_DELAY_OPTIONS
]
buttons.append(
{
"placeholder": {"type": "plain_text", "text": "Silence", "emoji": True},
"type": "static_select",
"options": silence_options,
"action_id": ScenarioStep.get_step("distribute_alerts", "SilenceGroupStep").routing_uid(),
}
)
else:
buttons.append(
{
"text": {"type": "plain_text", "text": "Unsilence", "emoji": True},
"type": "button",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step("distribute_alerts", "UnSilenceGroupStep").routing_uid(),
},
)
buttons.append(
{
"text": {"type": "plain_text", "text": "Responders", "emoji": True},
"type": "button",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step("manage_responders", "StartManageResponders").routing_uid(),
},
)
attach_button = {
"text": {"type": "plain_text", "text": "Attach to ...", "emoji": True},
"type": "button",
"action_id": ScenarioStep.get_step("distribute_alerts", "SelectAttachGroupStep").routing_uid(),
"value": self._alert_group_action_value(),
}
buttons.append(attach_button)
else:
buttons.append(
{
"text": {"type": "plain_text", "text": "Unresolve", "emoji": True},
"type": "button",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step("distribute_alerts", "UnResolveGroupStep").routing_uid(),
},
)
if self.alert_group.channel.is_available_for_custom_templates:
buttons.append(
{
"text": {"type": "plain_text", "text": ":mag: Format Alert", "emoji": True},
"type": "button",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step(
"alertgroup_appearance", "OpenAlertAppearanceDialogStep"
).routing_uid(),
},
)
# Resolution notes button
resolution_notes_count = self.alert_group.resolution_notes.count()
resolution_notes_button = {
def _make_button(text, action_id_step_class_name, action_id_scenario_step="distribute_alerts"):
return {
"text": {
"type": "plain_text",
"text": "Resolution notes [{}]".format(resolution_notes_count),
"text": text,
"emoji": True,
},
"type": "button",
"action_id": ScenarioStep.get_step("resolution_note", "ResolutionNoteModalStep").routing_uid(),
"value": self._alert_group_action_value(resolution_note_window_action="edit"),
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step(action_id_scenario_step, action_id_step_class_name).routing_uid(),
}
if resolution_notes_count == 0:
resolution_notes_button["style"] = "primary"
resolution_notes_button["text"]["text"] = "Add Resolution notes"
acknowledge_button = _make_button("Acknowledge", "AcknowledgeGroupStep")
unacknowledge_button = _make_button("Unacknowledge", "UnAcknowledgeGroupStep")
resolve_button = _make_button("Resolve", "ResolveGroupStep")
unresolve_button = _make_button("Unresolve", "UnResolveGroupStep")
unsilence_button = _make_button("Unsilence", "UnSilenceGroupStep")
responders_button = _make_button("Responders", "StartManageResponders", "manage_responders")
attach_button = _make_button("Attach to ...", "SelectAttachGroupStep")
format_alert_button = _make_button(
":mag: Format Alert", "OpenAlertAppearanceDialogStep", "alertgroup_appearance"
)
resolution_notes_count = alert_group.resolution_notes.count()
resolution_notes_button = {
"text": {
"type": "plain_text",
"text": f"Resolution notes [{resolution_notes_count}]",
"emoji": True,
},
"type": "button",
"action_id": ScenarioStep.get_step("resolution_note", "ResolutionNoteModalStep").routing_uid(),
"value": self._alert_group_action_value(resolution_note_window_action="edit"),
}
if resolution_notes_count == 0:
resolution_notes_button["style"] = "primary"
resolution_notes_button["text"]["text"] = "Add Resolution notes"
silence_button = {
"placeholder": {
"type": "plain_text",
"text": "Silence",
"emoji": True,
},
"type": "static_select",
"options": [
{
"text": {"type": "plain_text", "text": text, "emoji": True},
"value": self._alert_group_action_value(delay=value),
}
for value, text in AlertGroup.SILENCE_DELAY_OPTIONS
],
"action_id": ScenarioStep.get_step("distribute_alerts", "SilenceGroupStep").routing_uid(),
}
declare_incident_button = {
"type": "button",
"text": {
"type": "plain_text",
"text": ":fire: Declare incident",
"emoji": True,
},
"value": "declare_incident",
"url": self.alert_group.declare_incident_link,
"action_id": ScenarioStep.get_step("declare_incident", "DeclareIncidentStep").routing_uid(),
}
buttons = []
if not alert_group.is_maintenance_incident:
if not alert_group.resolved:
if not alert_group.acknowledged:
buttons.append(acknowledge_button)
else:
if grafana_incident_enabled:
buttons.append(declare_incident_button)
buttons.append(unacknowledge_button)
buttons.extend(
[
resolve_button,
unsilence_button if alert_group.silenced else silence_button,
responders_button,
attach_button,
]
)
else:
buttons.append(unresolve_button)
if integration.is_available_for_custom_templates:
buttons.append(format_alert_button)
buttons.append(resolution_notes_button)
# Declare incident button
if self.alert_group.channel.organization.is_grafana_incident_enabled:
incident_button = {
"type": "button",
"text": {"type": "plain_text", "text": ":fire: Declare incident", "emoji": True},
"value": "declare_incident",
"url": self.alert_group.declare_incident_link,
"action_id": ScenarioStep.get_step("declare_incident", "DeclareIncidentStep").routing_uid(),
}
buttons.append(incident_button)
if grafana_incident_enabled and not alert_group.acknowledged:
buttons.append(declare_incident_button)
else:
if not self.alert_group.resolved:
buttons.append(
{
"text": {"type": "plain_text", "text": "Resolve", "emoji": True},
"type": "button",
"style": "primary",
"value": self._alert_group_action_value(),
"action_id": ScenarioStep.get_step("distribute_alerts", "ResolveGroupStep").routing_uid(),
},
)
blocks = [{"type": "actions", "elements": buttons}]
return blocks
if not alert_group.resolved:
buttons.append(resolve_button)
return [{"type": "actions", "elements": buttons}]
def _get_invitation_attachment(self):
from apps.alerts.models import Invitation

View file

@ -38,7 +38,7 @@ def test_slack_renderer_unacknowledge_button(
alert_group = make_alert_group(alert_receive_channel, acknowledged=True)
make_alert(alert_group=alert_group, raw_request_data={})
elements = AlertGroupSlackRenderer(alert_group).render_alert_group_attachments()[0]["blocks"][0]["elements"]
elements = AlertGroupSlackRenderer(alert_group).render_alert_group_attachments()[1]["blocks"][0]["elements"]
button = elements[0]
assert button["text"]["text"] == "Unacknowledge"
@ -82,7 +82,7 @@ def test_slack_renderer_unresolve_button(make_organization, make_alert_receive_c
alert_group = make_alert_group(alert_receive_channel, resolved=True)
make_alert(alert_group=alert_group, raw_request_data={})
elements = AlertGroupSlackRenderer(alert_group).render_alert_group_attachments()[0]["blocks"][0]["elements"]
elements = AlertGroupSlackRenderer(alert_group).render_alert_group_attachments()[1]["blocks"][0]["elements"]
button = elements[0]
assert button["text"]["text"] == "Unresolve"