Skip to content

Commit

Permalink
Better summary and impact updates (#189)
Browse files Browse the repository at this point in the history
* Better summary and impact updates
Prior to this change, the summary and impact commands would overwrite whatever was currently
set for the incident. In most cases, our understanding of these develops over time, so we'd
like to be update and refine what we've previously set.

This change introduces actions and dialogs to update the summary and impact from what was previously
set, making it easier for us to develop meaningful and thorough statements over time.
  • Loading branch information
evnsio authored Nov 15, 2019
1 parent 56de528 commit 65292bb
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 16 deletions.
3 changes: 3 additions & 0 deletions response/slack/incident_commands/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import impact, incident_commands, summary

__all__ = (impact, incident_commands, summary)
106 changes: 106 additions & 0 deletions response/slack/incident_commands/impact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import json
import logging

from response.core.models import Incident
from response.slack import block_kit, dialog_builder
from response.slack.decorators import ActionContext, action_handler, dialog_handler
from response.slack.decorators.incident_command import __default_incident_command
from response.slack.models import CommsChannel

logger = logging.getLogger(__name__)

UPDATE_CURRENT_IMPACT_ACTION = "update-current-impact-action"
SET_NEW_IMPACT_ACTION = "set-new-impact-action"
PROPOSED_MESSAGE_BLOCK_ID = "proposed"
UPDATE_IMPACT_DIALOG = "update-impact-dialog"

NO_IMPACT_TEXT = "The impact of this incident hasn't been set yet."
CURRENT_TITLE = "*This is the current impact:*\n"
PROPOSED_TITLE = "*Or would you like to update the impact to this?*\n"
IMPACT_UPDATED_TITLE = "*The impact has been updated to:*\n"
CHANGE_BUTTON_TEXT = "Change"
ACCEPT_PROPOSED_TEXT = "Yes"


@__default_incident_command(["impact"], helptext="Explain the impact of this")
def update_impact(incident: Incident, user_id: str, message: str):
# Easy case. No impact currently and one has been provided
if message and not incident.impact:
incident.impact = message
incident.save()
return True, f"{IMPACT_UPDATED_TITLE}{message}"

# Either no new impact has been provided, or one already exists
msg = block_kit.Message()
msg.add_block(
block_kit.Section(
block_id="update",
text=block_kit.Text(f"{CURRENT_TITLE}{incident.impact or NO_IMPACT_TEXT}"),
accessory=block_kit.Button(
CHANGE_BUTTON_TEXT, UPDATE_CURRENT_IMPACT_ACTION, value=incident.pk
),
)
)

# if the user has supplied a message, provide the option for them to set it without
# retyping in the dialog
if message:
msg.add_block(
block_kit.Section(
block_id=PROPOSED_MESSAGE_BLOCK_ID,
text=block_kit.Text(f"{PROPOSED_TITLE}{message}"),
accessory=block_kit.Button(
ACCEPT_PROPOSED_TEXT, SET_NEW_IMPACT_ACTION, value=incident.pk
),
)
)

comms_channel = CommsChannel.objects.get(incident=incident)
msg.send(comms_channel.channel_id)
return True, None


@action_handler(SET_NEW_IMPACT_ACTION)
def handle_set_new_impact(action_context: ActionContext):
for block in action_context.message["blocks"]:
print("Looking at block", block)
if block["block_id"] == PROPOSED_MESSAGE_BLOCK_ID:
impact = block["text"]["text"].replace(PROPOSED_TITLE, "")
action_context.incident.impact = impact
action_context.incident.save()

comms_channel = CommsChannel.objects.get(incident=action_context.incident)
comms_channel.post_in_channel(f"{IMPACT_UPDATED_TITLE}{impact}")
return


@action_handler(UPDATE_CURRENT_IMPACT_ACTION)
def handle_open_impact_dialog(action_context: ActionContext):
dialog = dialog_builder.Dialog(
title="Update Impact",
submit_label="Update",
state=action_context.incident.pk,
elements=[
dialog_builder.TextArea(
label="Impact",
name="impact",
optional=False,
value=action_context.incident.impact,
)
],
)

dialog.send_open_dialog(UPDATE_IMPACT_DIALOG, action_context.trigger_id)


@dialog_handler(UPDATE_IMPACT_DIALOG)
def update_status_page(
user_id: str, channel_id: str, submission: json, response_url: str, state: json
):
incident_id = state
incident = Incident.objects.get(pk=incident_id)
incident.impact = submission["impact"]
incident.save()

comms_channel = CommsChannel.objects.get(incident=incident)
comms_channel.post_in_channel(f'{IMPACT_UPDATED_TITLE}{submission["impact"]}')
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,6 @@ def send_help_text(incident: Incident, user_id: str, message: str):
return True, get_help()


@__default_incident_command(
["summary"], helptext="Provide a summary of what's going on"
)
def update_summary(incident: Incident, user_id: str, message: str):
incident.summary = message
incident.save()
return True, None


@__default_incident_command(["impact"], helptext="Explain the impact of this")
def update_impact(incident: Incident, user_id: str, message: str):
incident.impact = message
incident.save()
return True, None


@__default_incident_command(["lead"], helptext="Assign someone as the incident lead")
def set_incident_lead(incident: Incident, user_id: str, message: str):
assignee = reference_to_id(message) or user_id
Expand Down
112 changes: 112 additions & 0 deletions response/slack/incident_commands/summary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import json
import logging

from response.core.models import Incident
from response.slack import block_kit, dialog_builder
from response.slack.decorators import ActionContext, action_handler, dialog_handler
from response.slack.decorators.incident_command import __default_incident_command
from response.slack.models import CommsChannel

logger = logging.getLogger(__name__)

UPDATE_CURRENT_SUMMARY_ACTION = "update-current-summary-action"
SET_NEW_SUMMARY_ACTION = "set-new-summary-action"
PROPOSED_MESSAGE_BLOCK_ID = "proposed"
UPDATE_SUMMARY_DIALOG = "update-summary-dialog"

NO_SUMMARY_TEXT = "This incident doesn't have a summary yet."
CURRENT_TITLE = "*This is the current summary:*\n"
PROPOSED_TITLE = "*Or would you like to update the summary to this?*\n"
SUMMARY_UPDATED_TITLE = "*The summary has been updated to:*\n"
CHANGE_BUTTON_TEXT = "Change"
ACCEPT_PROPOSED_TEXT = "Yes"


@__default_incident_command(
["summary"], helptext="Provide a summary of what's going on"
)
def update_summary(incident: Incident, user_id: str, message: str):
# Easy case. No summary currently and one has been provided
if message and not incident.summary:
incident.summary = message
incident.save()
return True, f"{SUMMARY_UPDATED_TITLE}{message}"

# Either no new summary has been provided, or one already exists
msg = block_kit.Message()

msg.add_block(
block_kit.Section(
block_id="update",
text=block_kit.Text(
f"{CURRENT_TITLE}{incident.summary or NO_SUMMARY_TEXT}"
),
accessory=block_kit.Button(
CHANGE_BUTTON_TEXT, UPDATE_CURRENT_SUMMARY_ACTION, value=incident.pk
),
)
)

# if the user has supplied a message, provide the option for them to set it without
# retyping in the dialog
if message:
msg.add_block(block_kit.Divider())
msg.add_block(
block_kit.Section(
block_id=PROPOSED_MESSAGE_BLOCK_ID,
text=block_kit.Text(f"{PROPOSED_TITLE}{message}"),
accessory=block_kit.Button(
ACCEPT_PROPOSED_TEXT, SET_NEW_SUMMARY_ACTION, value=incident.pk
),
)
)

comms_channel = CommsChannel.objects.get(incident=incident)
msg.send(comms_channel.channel_id)
return True, None


@action_handler(SET_NEW_SUMMARY_ACTION)
def handle_set_new_summary(action_context: ActionContext):
for block in action_context.message["blocks"]:
print("Looking at block", block)
if block["block_id"] == PROPOSED_MESSAGE_BLOCK_ID:
summary = block["text"]["text"].replace(PROPOSED_TITLE, "")
action_context.incident.summary = summary
action_context.incident.save()

comms_channel = CommsChannel.objects.get(incident=action_context.incident)
comms_channel.post_in_channel(f"{SUMMARY_UPDATED_TITLE}{summary}")
return


@action_handler(UPDATE_CURRENT_SUMMARY_ACTION)
def handle_open_summary_dialog(action_context: ActionContext):
dialog = dialog_builder.Dialog(
title="Update Summary",
submit_label="Update",
state=action_context.incident.pk,
elements=[
dialog_builder.TextArea(
label="Summary",
name="summary",
optional=False,
value=action_context.incident.summary,
)
],
)

dialog.send_open_dialog(UPDATE_SUMMARY_DIALOG, action_context.trigger_id)


@dialog_handler(UPDATE_SUMMARY_DIALOG)
def update_status_page(
user_id: str, channel_id: str, submission: json, response_url: str, state: json
):
incident_id = state
incident = Incident.objects.get(pk=incident_id)
incident.summary = submission["summary"]
incident.save()

comms_channel = CommsChannel.objects.get(incident=incident)
comms_channel.post_in_channel(f'{SUMMARY_UPDATED_TITLE}{submission["summary"]}')

0 comments on commit 65292bb

Please sign in to comment.