slack ¤
Modules:
-
admin– -
factories– -
management– -
messages– -
migrations– -
models– -
rules–Rules for publishing incidents in channels.
-
signals– -
slack_app– -
slack_incident_context– -
slack_templating– -
tasks– -
utils– -
views–
admin ¤
Classes:
Functions:
-
ask_key_timestamps–Will send a message to the Incident conversation (if it exists) to ask for key events.
ConversationAdmin ¤
Bases: ModelAdmin[Conversation]
Methods:
-
get_queryset–Restrict the queryset to only include conversations that are not IncidentChannels. Incident channels are managed in the IncidentChannelAdmin.
get_queryset ¤
get_queryset(request: HttpRequest) -> QuerySet[Conversation]
Restrict the queryset to only include conversations that are not IncidentChannels. Incident channels are managed in the IncidentChannelAdmin.
Source code in src/firefighter/slack/admin.py
ask_key_timestamps ¤
ask_key_timestamps(self: IncidentAdmin, request: HttpRequest, queryset: QuerySet[Incident]) -> None
Will send a message to the Incident conversation (if it exists) to ask for key events. TODO Error handling.
Source code in src/firefighter/slack/admin.py
factories ¤
Classes:
-
SlackProvider–Custom Faker provider for generating Slack IDs.
SlackProvider ¤
Bases: BaseProvider
Custom Faker provider for generating Slack IDs.
management ¤
Modules:
-
commands–
commands ¤
Modules:
-
switch_test_users–Django management command to switch Slack user IDs for test environment.
switch_test_users ¤
Django management command to switch Slack user IDs for test environment.
This command: 1. Fetches all users from the test Slack workspace 2. Generates a mapping file based on email addresses 3. Updates the database with test Slack user IDs
Classes:
-
Command–
Command ¤
Bases: BaseCommand
Methods:
-
handle–Main command handler.
handle ¤
Main command handler.
Source code in src/firefighter/slack/management/commands/switch_test_users.py
messages ¤
Modules:
-
base– -
slack_messages–
base ¤
Classes:
-
SlackMessageStrategy–Define how should the message be posted.
-
SlackMessageSurface–Base class for Slack messages, which are sent to a channel or a user.
SlackMessageStrategy ¤
Bases: Enum
Define how should the message be posted.
append: add the message to the channel, even if a message with the same type has already been posted.replace: replace the last message with the same type (push new one, delete old one)update: update in place the last message with the same type
SlackMessageSurface ¤
Bases: ABC
Base class for Slack messages, which are sent to a channel or a user.
This provides a common interface to send messages with text, blocks and metadata.
This is helpful to send messages but also to save them in DB.
Methods:
-
get_blocks–Returns the blocks of the message.
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
get_text–Returns the text of the message.
-
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Attributes:
-
strategy(SlackMessageStrategy) –Alphanumeric ID, starting with a letter, that may contain underscores.
Source code in src/firefighter/slack/messages/base.py
strategy class-attribute instance-attribute ¤
strategy: SlackMessageStrategy = SlackMessageStrategy.APPEND
Alphanumeric ID, starting with a letter, that may contain underscores.
get_blocks ¤
get_blocks() -> list[Block]
Returns the blocks of the message.
Returns:
-
list[Block]–list[Block]: List of Slack Blocks for the message. Default is the text as a SectionBlock.
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
slack_messages ¤
Classes:
-
SlackMessageIncidentDeclaredAnnouncement– -
SlackMessageIncidentDeclaredAnnouncementGeneral– -
SlackMessageIncidentPostMortemCreated– -
SlackMessageIncidentPostMortemCreatedAnnouncement–Message to announce post-mortem creation in #critical-incidents (tech_incidents tag).
-
SlackMessageIncidentProcessReminder–Reminder that a mitigated incident still has to be driven through to closure.
-
SlackMessageIncidentProcessReminderAnnouncement–Announcement version of the process reminder, for the #critical-incidents channel.
-
SlackMessageIncidentRolesUpdated–The message to post in the incident channel when the roles are updated.
SlackMessageIncidentDeclaredAnnouncement ¤
SlackMessageIncidentDeclaredAnnouncement(incident: Incident)
Bases: SlackMessageSurface
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/slack_messages.py
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
SlackMessageIncidentDeclaredAnnouncementGeneral ¤
SlackMessageIncidentDeclaredAnnouncementGeneral(incident: Incident)
Bases: SlackMessageSurface
Parameters:
-
incident(Incident) –Your incident
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Attributes:
-
strategy(SlackMessageStrategy) –Alphanumeric ID, starting with a letter, that may contain underscores.
Source code in src/firefighter/slack/messages/slack_messages.py
strategy class-attribute instance-attribute ¤
strategy: SlackMessageStrategy = SlackMessageStrategy.APPEND
Alphanumeric ID, starting with a letter, that may contain underscores.
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
SlackMessageIncidentPostMortemCreated ¤
SlackMessageIncidentPostMortemCreated(incident: Incident)
Bases: SlackMessageSurface
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
get_text–Generate text with links to all available post-mortems.
-
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Attributes:
-
strategy(SlackMessageStrategy) –Alphanumeric ID, starting with a letter, that may contain underscores.
Source code in src/firefighter/slack/messages/slack_messages.py
strategy class-attribute instance-attribute ¤
strategy: SlackMessageStrategy = SlackMessageStrategy.APPEND
Alphanumeric ID, starting with a letter, that may contain underscores.
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
get_text ¤
get_text() -> str
Generate text with links to all available post-mortems.
Source code in src/firefighter/slack/messages/slack_messages.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
SlackMessageIncidentPostMortemCreatedAnnouncement ¤
SlackMessageIncidentPostMortemCreatedAnnouncement(incident: Incident)
Bases: SlackMessageSurface
Message to announce post-mortem creation in #critical-incidents (tech_incidents tag).
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
get_text–Generate announcement text for critical incidents channel.
-
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Attributes:
-
strategy(SlackMessageStrategy) –Alphanumeric ID, starting with a letter, that may contain underscores.
Source code in src/firefighter/slack/messages/slack_messages.py
strategy class-attribute instance-attribute ¤
strategy: SlackMessageStrategy = SlackMessageStrategy.APPEND
Alphanumeric ID, starting with a letter, that may contain underscores.
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
SlackMessageIncidentProcessReminder ¤
Bases: SlackMessageSurface
Reminder that a mitigated incident still has to be driven through to closure.
Sent to the incident channel once the incident has sat mitigated for FF_PROCESS_REMINDER_FIRST_DELAY, then again every FF_PROCESS_REMINDER_REPEAT_DELAY of inactivity. The ask depends on the incident: complete the post-mortem when the priority requires one (P1/P2), submit the key events and close otherwise (P3).
The id keeps its historical value: it is stored on every reminder already sent (Message.ff_type) and is what the task reads to know when it last reminded.
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Attributes:
-
strategy(SlackMessageStrategy) –Alphanumeric ID, starting with a letter, that may contain underscores.
Source code in src/firefighter/slack/messages/slack_messages.py
strategy class-attribute instance-attribute ¤
strategy: SlackMessageStrategy = SlackMessageStrategy.APPEND
Alphanumeric ID, starting with a letter, that may contain underscores.
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
SlackMessageIncidentProcessReminderAnnouncement ¤
SlackMessageIncidentProcessReminderAnnouncement(incident: Incident)
Bases: SlackMessageSurface
Announcement version of the process reminder, for the #critical-incidents channel.
Only published on the first reminder: the repeats stay in the incident channel.
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Attributes:
-
strategy(SlackMessageStrategy) –Alphanumeric ID, starting with a letter, that may contain underscores.
Source code in src/firefighter/slack/messages/slack_messages.py
strategy class-attribute instance-attribute ¤
strategy: SlackMessageStrategy = SlackMessageStrategy.APPEND
Alphanumeric ID, starting with a letter, that may contain underscores.
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
SlackMessageIncidentRolesUpdated ¤
SlackMessageIncidentRolesUpdated(
incident: Incident, incident_update: IncidentUpdate | None, *, first_update: bool = False, updated_fields: list[str] | None = None
)
Bases: SlackMessageSurface
The message to post in the incident channel when the roles are updated.
Parameters:
-
incident(Incident) –Your incident.
-
incident_update(IncidentUpdate) –The opening incident update.
-
first_update(bool, default:False) –Whether this is the first update of the incident. Defaults to False.
-
updated_fields(list[str], default:None) –The fields that were updated. Defaults to None.
Methods:
-
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Attributes:
-
strategy(SlackMessageStrategy) –Alphanumeric ID, starting with a letter, that may contain underscores.
Source code in src/firefighter/slack/messages/slack_messages.py
strategy class-attribute instance-attribute ¤
strategy: SlackMessageStrategy = SlackMessageStrategy.APPEND
Alphanumeric ID, starting with a letter, that may contain underscores.
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
migrations ¤
Modules:
0006_copy_components_to_incident_categories ¤
Functions:
-
copy_components_to_incident_categories–Copy all component M2M relationships to incident_categories M2M relationships
-
reverse_copy_components_to_incident_categories–Reverse: copy incident_categories relationships back to components
copy_components_to_incident_categories ¤
Copy all component M2M relationships to incident_categories M2M relationships
Source code in src/firefighter/slack/migrations/0006_copy_components_to_incident_categories.py
reverse_copy_components_to_incident_categories ¤
Reverse: copy incident_categories relationships back to components
Source code in src/firefighter/slack/migrations/0006_copy_components_to_incident_categories.py
0009_add_postmortem_reminder_periodic_task ¤
Functions:
-
create_postmortem_reminder_task–Create periodic task for post-mortem reminders.
-
remove_postmortem_reminder_task–Remove the periodic task on migration rollback.
create_postmortem_reminder_task ¤
Create periodic task for post-mortem reminders.
Runs twice daily at 10:00 AM and 3:00 PM to check for incidents mitigated 5+ days ago.
Source code in src/firefighter/slack/migrations/0009_add_postmortem_reminder_periodic_task.py
remove_postmortem_reminder_task ¤
Remove the periodic task on migration rollback.
Source code in src/firefighter/slack/migrations/0009_add_postmortem_reminder_periodic_task.py
models ¤
Modules:
-
conversation– -
incident_channel– -
message– -
sos– -
user– -
user_group–
conversation ¤
Classes:
-
Conversation–Model a Slack API Conversation.
Conversation ¤
Bases: Model
Model a Slack API Conversation. A Slack Conversation can be a public channel, a private channel, a direct message, or a multi-person direct message. Reference: https://api.slack.com/types/conversation.
Methods:
-
add_bookmark–Convenience method to add a bookmark on this conversation.
-
send_message–Convenience method to send a message on this conversation.
-
send_message_and_save–Convenience method to send a message on this conversation.
-
send_message_ephemeral–Convenience method to send an ephemeral message on this conversation.
Attributes:
-
deep_link(str) –Deep link (
slack://) to the conversation in the Slack client. -
link(str) –Regular HTTPS link to the conversation through Slack.com.
add_bookmark ¤
add_bookmark(
title: str,
_type: str = "link",
emoji: str | None = None,
entity_id: str | None = None,
link: str | None = None,
parent_id: str | None = None,
client: WebClient = DefaultWebClient,
**kwargs: Any
) -> None
Convenience method to add a bookmark on this conversation.
Source code in src/firefighter/slack/models/conversation.py
send_message ¤
send_message(
text: str | None = None, blocks: Sequence[dict[str, Any] | Block] | None = None, client: WebClient = DefaultWebClient, **kwargs: Any
) -> None
Convenience method to send a message on this conversation.
Source code in src/firefighter/slack/models/conversation.py
send_message_and_save ¤
send_message_and_save(
message: SlackMessageSurface,
client: WebClient = DefaultWebClient,
strategy: SlackMessageStrategy | None = None,
strategy_args: dict[str, Any] | None = None,
*,
pin: bool = False
) -> SlackResponse
Convenience method to send a message on this conversation.
Source code in src/firefighter/slack/models/conversation.py
send_message_ephemeral ¤
send_message_ephemeral(message: SlackMessageSurface, user: SlackUser | str, client: WebClient = DefaultWebClient, **kwargs: Any) -> None
Convenience method to send an ephemeral message on this conversation. user, channel, blocks, text and metadata should not be passed in kwargs.
Source code in src/firefighter/slack/models/conversation.py
incident_channel ¤
Classes:
IncidentChannel ¤
Bases: Conversation
Methods:
-
add_bookmark–Convenience method to add a bookmark on this conversation.
-
invite_users–Invite users to the conversation, if they have a Slack user linked and are active.
-
send_message–Convenience method to send a message on this conversation.
-
send_message_and_save–Convenience method to send a message on this conversation.
-
send_message_ephemeral–Convenience method to send an ephemeral message on this conversation.
Attributes:
-
deep_link(str) –Deep link (
slack://) to the conversation in the Slack client. -
link(str) –Regular HTTPS link to the conversation through Slack.com.
add_bookmark ¤
add_bookmark(
title: str,
_type: str = "link",
emoji: str | None = None,
entity_id: str | None = None,
link: str | None = None,
parent_id: str | None = None,
client: WebClient = DefaultWebClient,
**kwargs: Any
) -> None
Convenience method to add a bookmark on this conversation.
Source code in src/firefighter/slack/models/conversation.py
invite_users ¤
Invite users to the conversation, if they have a Slack user linked and are active.
Try to invite all users as batch, but if some fail, continue individually.
Source code in src/firefighter/slack/models/incident_channel.py
send_message ¤
send_message(
text: str | None = None, blocks: Sequence[dict[str, Any] | Block] | None = None, client: WebClient = DefaultWebClient, **kwargs: Any
) -> None
Convenience method to send a message on this conversation.
Source code in src/firefighter/slack/models/conversation.py
send_message_and_save ¤
send_message_and_save(
message: SlackMessageSurface,
client: WebClient = DefaultWebClient,
strategy: SlackMessageStrategy | None = None,
strategy_args: dict[str, Any] | None = None,
*,
pin: bool = False
) -> SlackResponse
Convenience method to send a message on this conversation.
Source code in src/firefighter/slack/models/conversation.py
send_message_ephemeral ¤
send_message_ephemeral(message: SlackMessageSurface, user: SlackUser | str, client: WebClient = DefaultWebClient, **kwargs: Any) -> None
Convenience method to send an ephemeral message on this conversation. user, channel, blocks, text and metadata should not be passed in kwargs.
Source code in src/firefighter/slack/models/conversation.py
message ¤
Classes:
-
Message–Model a Slack API Conversation.
Message ¤
Bases: Model
Model a Slack API Conversation. A Slack Conversation can be a public channel, a private channel, a direct message, or a multi-person direct message. Reference: https://api.slack.com/types/conversation.
sos ¤
Classes:
-
Sos–A SOS is a target with a name, a conversation, and optionally a user group.
Sos ¤
Bases: Model
A SOS is a target with a name, a conversation, and optionally a user group.
Incident responders can use it with /incident sos to ask for help to a specific group of people.
Helpers will be notified in the selected conversation, and the user group will be mentioned (or @here if no user group is selected)
Attributes:
-
usergroup_slack_fmt(str) –Returns either
@usergroupor@heredepending on usergroup presence.
user ¤
Classes:
-
SlackUser–Holds data about a Slack User, linked to an :model:
incidents.user. -
SlackUserManager–
SlackUser ¤
Bases: Model
Holds data about a Slack User, linked to an :model:incidents.user. slack_id field is not used as PK, as it is only guaranteed by Slack to be unique in pair with a team_id.
Methods:
-
send_private_message–Send a private message to the user.
Attributes:
url property ¤
url: str
Returns an HTTPS ULR to the Slack user's profile. For deep linking, use link instead.
send_private_message ¤
send_private_message(message: SlackMessageSurface, client: WebClient = DefaultWebClient, **kwargs: Any) -> None
Send a private message to the user.
Source code in src/firefighter/slack/models/user.py
SlackUserManager ¤
Bases: Manager['SlackUser']
Methods:
-
get_user_by_slack_id–Returns a User from DB if it exists, or fetch its info from Slack, save it to DB and returns it.
-
unpack_user_info–Returns a dict contains fields for the SlackUser, from a SlackResponse.
-
upsert_by_email–Returns a User from DB if it exists, or fetch its info from Slack, save it to DB and returns it.
get_user_by_slack_id ¤
get_user_by_slack_id(slack_id: str, defaults: dict[str, str] | None = None, client: WebClient = DefaultWebClient) -> User | None
Returns a User from DB if it exists, or fetch its info from Slack, save it to DB and returns it.
Source code in src/firefighter/slack/models/user.py
unpack_user_info staticmethod ¤
Returns a dict contains fields for the SlackUser, from a SlackResponse. email, name and id should always be returned.
Source code in src/firefighter/slack/models/user.py
upsert_by_email ¤
Returns a User from DB if it exists, or fetch its info from Slack, save it to DB and returns it.
Source code in src/firefighter/slack/models/user.py
user_group ¤
Classes:
-
UserGroup–Model a Slack API UserGroup.
-
UserGroupManager–
UserGroup ¤
UserGroupManager ¤
Bases: Manager['UserGroup']
Methods:
-
fetch_all_usergroups_data–Fetch all usergroups from firefighter.slack.
-
fetch_usergroup–Import a "usergroup" from Slack and return its UserGroup model.
fetch_all_usergroups_data staticmethod ¤
fetch_all_usergroups_data(client: WebClient = DefaultWebClient, *, include_users: bool = False) -> list[dict[str, Any]]
Fetch all usergroups from firefighter.slack.
Returns the list of usergroups
Source code in src/firefighter/slack/models/user_group.py
fetch_usergroup staticmethod ¤
fetch_usergroup(
group_slack_id: str | None = None, group_handle: str | None = None, client: WebClient = DefaultWebClient, **kwargs: Any
) -> UserGroup | None
Import a "usergroup" from Slack and return its UserGroup model. Either group_slack_id or group_handle must be provided.
Parameters:
-
group_slack_id(str | None, default:None) –The Slack usergroup id of the usergroup to import. Usually starts with
S. Defaults to None. -
group_handle(str | None, default:None) –Handle (@xxx) of the usergroup to import. Defaults to None.
-
client(WebClient, default:DefaultWebClient) –Slack client. Defaults to DefaultWebClient.
-
**kwargs(Any, default:{}) –Additional keyword arguments to pass to created UserGroup model.
Returns:
-
UserGroup | None–UserGroup | None: UserGroup model or None if not found
Source code in src/firefighter/slack/models/user_group.py
rules ¤
Rules for publishing incidents in channels.
This module may be removed in a future version.
Functions:
-
should_publish_pm_in_general_channel–Determine if post-mortem creation should be announced in #critical-incidents.
should_publish_pm_in_general_channel ¤
Determine if post-mortem creation should be announced in #critical-incidents.
Post-mortems are announced for P1-P3 production incidents that are not private and require a post-mortem.
Parameters:
-
incident(Incident) –The incident for which a post-mortem was created.
Returns:
-
bool–True if the post-mortem creation should be announced in tech_incidents channel.
Source code in src/firefighter/slack/rules.py
signals ¤
Modules:
-
create_incident_conversation–This module contains the logic to open an incident channel and invite responders.
-
get_users– -
incident_updated–
create_incident_conversation ¤
This module contains the logic to open an incident channel and invite responders.
XXX It might be divided into two signals/tasks, one for creating, one for inviting. XXX Sending the end signal should be done by this signal's caller, not by this signal receiver directly.
Functions:
-
create_incident_slack_conversation–Main process to open an incident channel, set it up and invite responders. It MUST be called when an incident is created.
create_incident_slack_conversation ¤
Main process to open an incident channel, set it up and invite responders. It MUST be called when an incident is created.
Parameters:
-
incident(Incident) –The incident to open. It should be saved before calling this function, and have its first incident update created.
Kwargs
jira_extra_fields (dict): Optional dictionary of customer/seller fields for Jira ticket
Source code in src/firefighter/slack/signals/create_incident_conversation.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
get_users ¤
Functions:
-
get_invites_from_slack–New version using cached users instead of querying Slack API.
get_invites_from_slack ¤
New version using cached users instead of querying Slack API.
Source code in src/firefighter/slack/signals/get_users.py
incident_updated ¤
Functions:
-
incident_updated_broadcast_handler–Broadcast the update to the org-wide channels.
-
incident_updated_channel_maintenance_handler–Keep the incident channel name and topic in sync.
-
incident_updated_update_status_handler–Publish the status update and the Key Events form in the incident channel.
-
publish_broadcasts–Publishes the update to the org-wide broadcast channels.
-
publish_incident_channel_update–Publishes the status update and the Key Events form in the incident channel.
incident_updated_broadcast_handler ¤
incident_updated_broadcast_handler(
sender: Any, incident: Incident, incident_update: IncidentUpdate, updated_fields: list[str], **kwargs: Any
) -> None
Broadcast the update to the org-wide channels.
Kept out of the incident-channel handler on purpose: broadcast channels are independent, and losing one must never suppress what responders rely on.
Source code in src/firefighter/slack/signals/incident_updated.py
incident_updated_channel_maintenance_handler ¤
incident_updated_channel_maintenance_handler(
sender: Any, incident: Incident, incident_update: IncidentUpdate, updated_fields: list[str], **kwargs: Any
) -> None
Keep the incident channel name and topic in sync.
Registered on its own so a Slack failure here is contained by Signal.send_robust() instead of suppressing the publications below.
Source code in src/firefighter/slack/signals/incident_updated.py
incident_updated_update_status_handler ¤
incident_updated_update_status_handler(
sender: Any, incident: Incident, incident_update: IncidentUpdate, updated_fields: list[str], **kwargs: Any
) -> None
Publish the status update and the Key Events form in the incident channel.
Source code in src/firefighter/slack/signals/incident_updated.py
publish_broadcasts ¤
publish_broadcasts(
incident: Incident, incident_update: IncidentUpdate, *, status_changed: bool = False, old_priority: Priority | None = None
) -> None
Publishes the update to the org-wide broadcast channels.
Source code in src/firefighter/slack/signals/incident_updated.py
publish_incident_channel_update ¤
publish_incident_channel_update(incident: Incident, incident_update: IncidentUpdate, *, status_changed: bool = False) -> None
Publishes the status update and the Key Events form in the incident channel.
Source code in src/firefighter/slack/signals/incident_updated.py
slack_app ¤
Classes:
-
SlackApp–Subclass of the Slack App, as a singleton.
Functions:
-
slack_client–Adds a Slack client in
clientkwargs, if none is provided.
SlackApp ¤
Bases: App
Subclass of the Slack App, as a singleton.
slack_client ¤
Adds a Slack client in client kwargs, if none is provided.
Can be used as a decorator with @slack_client or as a function with slack_client(function).
Source code in src/firefighter/slack/slack_app.py
slack_incident_context ¤
Functions:
-
get_incident_from_app_home_element–Get an incident from an action, found in app home accessory.
-
get_incident_from_body_channel_id_in_command–Get an incident from a channel_id, found in commands.
-
get_incident_from_body_channel_id_in_message_shortcut–Get an incident from a channel.id, found in message shortcut.
-
get_incident_from_button_value–Try to get the incident ID from button value.
-
get_incident_from_context–Returns an Incident or None, from a Slack body.
-
get_incident_from_view_action–Get incident id from select incident in modal.
-
get_incident_from_view_submission_metadata–Get incident id from view modal metadata.
-
get_incident_from_view_submission_selected–Get incident id from select incident in modal.
-
get_user_from_context–Returns a User or None, from a Slack body.
get_incident_from_app_home_element ¤
Get an incident from an action, found in app home accessory.
Source code in src/firefighter/slack/slack_incident_context.py
get_incident_from_body_channel_id_in_command ¤
Get an incident from a channel_id, found in commands.
Source code in src/firefighter/slack/slack_incident_context.py
get_incident_from_body_channel_id_in_message_shortcut ¤
Get an incident from a channel.id, found in message shortcut.
Source code in src/firefighter/slack/slack_incident_context.py
get_incident_from_button_value ¤
Try to get the incident ID from button value.
Source code in src/firefighter/slack/slack_incident_context.py
get_incident_from_context ¤
Returns an Incident or None, from a Slack body.
Source code in src/firefighter/slack/slack_incident_context.py
get_incident_from_view_action ¤
Get incident id from select incident in modal.
Source code in src/firefighter/slack/slack_incident_context.py
get_incident_from_view_submission_metadata ¤
get_incident_from_view_submission_metadata(body: dict[str, Any]) -> Incident | Literal[False] | None
Get incident id from view modal metadata.
Source code in src/firefighter/slack/slack_incident_context.py
get_incident_from_view_submission_selected ¤
get_incident_from_view_submission_selected(body: dict[str, Any]) -> Incident | Literal[False] | None
Get incident id from select incident in modal.
Source code in src/firefighter/slack/slack_incident_context.py
get_user_from_context ¤
Returns a User or None, from a Slack body.
Source code in src/firefighter/slack/slack_incident_context.py
slack_templating ¤
Functions:
-
commander_ownership_block–Remind whoever holds command that they own driving the process, or that nobody does.
-
date_time–Common format for datetime.
-
md_quote_filter–Add > on newlines for MD quotes.
-
shorten_long–Shorten text while keeping newlines and most formatting.
-
user_slack_handle_or_name–Returns the Slack handle of the user in Slack MD format (
<@SLACK_ID>) or the user full name.
Attributes:
-
COMMANDER_ACTION_CLOSURE–Ownership sentence for incidents that close without a post-mortem.
-
COMMANDER_ACTION_OPENING–Ownership sentence for the start of the incident, when roles are first announced.
-
COMMANDER_ACTION_POSTMORTEM–Ownership sentence for incidents that require a post-mortem before closure.
-
COMMANDER_UNASSIGNED–Shown instead of a mention when nobody holds command.
-
ROLE_REASSIGNMENT_HINT–Invitation to hand a role over, with the consent of whoever picks it up.
COMMANDER_ACTION_CLOSURE module-attribute ¤
COMMANDER_ACTION_CLOSURE = "as *Incident Commander*, it's on you to get the key events submitted and to close this incident."
Ownership sentence for incidents that close without a post-mortem.
COMMANDER_ACTION_OPENING module-attribute ¤
COMMANDER_ACTION_OPENING = "you are the *Incident Commander*: you lead the process through to closure. You don't have to do all the work, but you are in charge of guiding the team — including making sure the post-mortem is carried out before the incident is closed."
Ownership sentence for the start of the incident, when roles are first announced.
COMMANDER_ACTION_POSTMORTEM module-attribute ¤
COMMANDER_ACTION_POSTMORTEM = "as *Incident Commander*, it's on you to organize the post-mortem and see it through before closure. You don't have to write it all yourself — you own getting it done."
Ownership sentence for incidents that require a post-mortem before closure.
COMMANDER_UNASSIGNED module-attribute ¤
COMMANDER_UNASSIGNED = (
"No *Incident Commander* is assigned on this incident — someone needs to take the role to drive it through to closure."
)
Shown instead of a mention when nobody holds command.
ROLE_REASSIGNMENT_HINT module-attribute ¤
ROLE_REASSIGNMENT_HINT = ":bulb: _Not the right person for a role? Talk it over in this channel so a more suitable responder can take it over, with their agreement, then reassign the role._"
Invitation to hand a role over, with the consent of whoever picks it up.
commander_ownership_block ¤
Remind whoever holds command that they own driving the process, or that nobody does.
Parameters:
-
incident(Incident) –the incident to read the commander from. Callers looping over incidents should
prefetch_related("roles_set__role_type", "roles_set__user__slack_user"). -
action(str) –the ownership sentence to use, e.g. COMMANDER_ACTION_POSTMORTEM.
Source code in src/firefighter/slack/slack_templating.py
date_time cached ¤
md_quote_filter ¤
shorten_long ¤
Shorten text while keeping newlines and most formatting.
Source code in src/firefighter/slack/slack_templating.py
user_slack_handle_or_name ¤
Returns the Slack handle of the user in Slack MD format (<@SLACK_ID>) or the user full name.
Source code in src/firefighter/slack/slack_templating.py
tasks ¤
Modules:
-
fetch_conversations_members– -
generate_dust_postmortem–Ask the Dust agent to fill in an incident's post-mortem.
-
reminder_postmortem– -
send_message– -
send_postmortem_reminders–Celery task reminding the Commander to drive a mitigated incident through to closure.
-
send_reminders– -
sync_timeline–Deferred re-sync of a corrected timeline, batched over a short window.
-
sync_users– -
update_usergroups_members– -
update_users–
fetch_conversations_members ¤
Functions:
-
fetch_conversations_members_from_slack–Update the members and metadata of Slack Conversations in DB, from Slack API.
-
fetch_conversations_members_from_slack_celery–Wrapper around the actual task, as Celery doesn't support passing Django models.
fetch_conversations_members_from_slack ¤
fetch_conversations_members_from_slack(
client: WebClient = DefaultWebClient, queryset: QuerySet[Conversation] | None = None
) -> list[Conversation]
Update the members and metadata of Slack Conversations in DB, from Slack API.
Only fetches conversations that are not IncidentChannels.
Parameters:
-
client(WebClient, default:DefaultWebClient) –Slack SDK client. Defaults to DefaultWebClient.
-
queryset(Optional[QuerySet[Conversation]], default:None) –Conversation to update. Defaults to None. If None, all applicable
Returns:
-
list[Conversation]–list[Conversation]: List of conversations that could not be updated.
Raises:
-
TypeError–If the members list is not a list.
Source code in src/firefighter/slack/tasks/fetch_conversations_members.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | |
fetch_conversations_members_from_slack_celery ¤
fetch_conversations_members_from_slack_celery(
*_args: Any, queryset: QuerySet[Conversation] | None = None, **_options: Any
) -> dict[str, list[str]]
Wrapper around the actual task, as Celery doesn't support passing Django models.
Source code in src/firefighter/slack/tasks/fetch_conversations_members.py
generate_dust_postmortem ¤
Ask the Dust agent to fill in an incident's post-mortem.
The first implementation posted an instruction addressed to the Dust bot in the incident channel and relied on the agent reading it. It did not work reliably, so Dust exposes a webhook for exactly this: the payload names the channel to work from and the Jira post-mortem to fill, and is signed with a shared secret.
The bot is still invited to the channel first: the agent reports back there, and a bot that is not a member cannot post.
Functions:
-
build_dust_payload–What the agent is given: the channel to read and the ticket to fill in.
-
sign_payload–sha256=<hex>HMAC of the exact bytes sent, as the webhook expects.
build_dust_payload ¤
What the agent is given: the channel to read and the ticket to fill in.
Dust does not impose a schema - "you define the structure based on your webhook source", and the agent's instructions and filters address the fields by path. So the two values the agent needs are sent as fields it can address directly, and message carries the same thing as prose for an agent that would rather read the instruction than the structure.
Source code in src/firefighter/slack/tasks/generate_dust_postmortem.py
sign_payload ¤
sha256=<hex> HMAC of the exact bytes sent, as the webhook expects.
Source code in src/firefighter/slack/tasks/generate_dust_postmortem.py
reminder_postmortem ¤
Functions:
-
publish_postmortem_reminder–XXX Should return a message object, not send it.
publish_postmortem_reminder ¤
publish_postmortem_reminder(incident: Incident, client: WebClient = DefaultWebClient) -> None
XXX Should return a message object, not send it.
Source code in src/firefighter/slack/tasks/reminder_postmortem.py
send_message ¤
Functions:
-
send_message–Sends a message to a channel. All arguments are passed to the Slack API.
send_message ¤
send_message(client: WebClient = DefaultWebClient, *args: Any, **kwargs: Any) -> dict[str, Any] | bytes
Sends a message to a channel. All arguments are passed to the Slack API.
Source code in src/firefighter/slack/tasks/send_message.py
send_postmortem_reminders ¤
Celery task reminding the Commander to drive a mitigated incident through to closure.
An incident that stays mitigated is not finished: P1/P2 still need their post-mortem, P3 still needs its key events and its closure. This task nudges whoever holds command once the incident has sat mitigated for its priority's postmortem_reminder_time, then again every postmortem_reminder_repeat_time for as long as nothing moves. Both live on the Priority, next to reminder_time, so they can be tuned per priority in the Django admin - including down to a few minutes to rehearse the flow.
Functions:
-
send_postmortem_reminders–Remind the Commander of every stalled mitigated incident to drive it to closure.
send_postmortem_reminders ¤
Remind the Commander of every stalled mitigated incident to drive it to closure.
The Celery name is kept for compatibility: it is stored in the PeriodicTask row created by the slack.0009 migration, and renaming it would leave Beat dispatching a task nobody registers.
Source code in src/firefighter/slack/tasks/send_postmortem_reminders.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | |
send_reminders ¤
Functions:
-
slack_save_reminder_message–Save the firefighter.slack.models.Message from a Slack response. First
argsis an firefighter.incidents.models.Incident ID.
slack_save_reminder_message ¤
slack_save_reminder_message(message_response_data: SlackResponse, *args: int, **_kwargs: Any) -> bool
Save the firefighter.slack.models.Message from a Slack response. First args is an firefighter.incidents.models.Incident ID.
Parameters:
-
message_response_data(dict) –SlackResponse data.
-
*args(int, default:()) –Expect one value, the firefighter.incidents.models.Incident ID.
-
**_kwargs(Any, default:{}) –Ignored.
Source code in src/firefighter/slack/tasks/send_reminders.py
sync_timeline ¤
Deferred re-sync of a corrected timeline, batched over a short window.
The timeline correction message saves every field on its own (see slack.views.modals.review_timeline.TimelineCorrection), so syncing from the save itself would mean one Jira round trip - and one "(edited)" refresh of the Key Events message - per keystroke. Corrections schedule this task instead: the first edit of a window arms it, the following ones ride along, and a single sync runs once the reviewer is done typing.
Functions:
-
schedule_timeline_sync–Arm one deferred sync for this incident, or ride along an armed one.
-
sync_corrected_timeline–Recompute metrics and push the corrected timeline to the post-mortem.
schedule_timeline_sync ¤
Arm one deferred sync for this incident, or ride along an armed one.
Returns whether this call armed the window. cache.add is the atomic check-and-set that makes concurrent edits (two people fixing different fields at once) schedule a single task rather than one each.
Source code in src/firefighter/slack/tasks/sync_timeline.py
sync_corrected_timeline ¤
sync_corrected_timeline(incident_id: int) -> None
Recompute metrics and push the corrected timeline to the post-mortem.
Source code in src/firefighter/slack/tasks/sync_timeline.py
sync_users ¤
Functions:
-
sync_users–Retrieves users from Slack and updates the database (e.g. name, new profile picture, email, active status...).
sync_users ¤
Retrieves users from Slack and updates the database (e.g. name, new profile picture, email, active status...).
Source code in src/firefighter/slack/tasks/sync_users.py
update_usergroups_members ¤
Functions:
-
update_usergroups_members_from_slack_celery–Wrapper around the actual task, as Celery doesn't support passing Django models.
update_usergroups_members_from_slack_celery ¤
update_usergroups_members_from_slack_celery(*args: Any, **options: Any) -> dict[str, list[str | None]]
Wrapper around the actual task, as Celery doesn't support passing Django models.
Source code in src/firefighter/slack/tasks/update_usergroups_members.py
update_users ¤
Functions:
-
update_users_from_slack–Retrieves users from Slack and updates the database (e.g. name, new profile picture, email, active status...).
update_users_from_slack ¤
Retrieves users from Slack and updates the database (e.g. name, new profile picture, email, active status...).
Source code in src/firefighter/slack/tasks/update_users.py
utils ¤
Functions:
-
channel_name_from_incident–Lowercase, truncated at 80 chars, this is obviously the channel #name.
-
get_slack_user_id_from_body–Get the slack user id from the body of a Slack request, in
user_idoruser.id. -
respond–Respond to the user, depending on where the message was coming from.
channel_name_from_incident ¤
Lowercase, truncated at 80 chars, this is obviously the channel #name.
The environment(s) are included in the channel name to clearly indicate scope. When multiple environments are affected, all are displayed sorted by priority. If the name exceeds 80 characters, environments are abbreviated progressively.
Source code in src/firefighter/slack/utils.py
get_slack_user_id_from_body ¤
Get the slack user id from the body of a Slack request, in user_id or user.id.
respond ¤
respond(
body: dict[str, Any], text: str = "", blocks: str | Sequence[dict[str, Any] | Block] | None = None, client: WebClient = DefaultWebClient
) -> None
Respond to the user, depending on where the message was coming from.
Source code in src/firefighter/slack/utils.py
views ¤
Modules:
-
events– -
modals– -
select_impact– -
views–
Classes:
-
CloseModal– -
ClosureReasonModal–Modal for closing an incident with a mandatory reason from early statuses.
-
KeyEvents– -
OnCallModal– -
OpenModal– -
SlackMessageReviewTimeline– -
UpdateModal–
CloseModal ¤
Bases: IncidentSelectableModalMixin, ModalForm[CloseIncidentFormSlack]
Methods:
-
handle_modal_fn–Handle response from /incident close modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
handle_modal_fn ¤
Handle response from /incident close modal.
Source code in src/firefighter/slack/views/modals/close.py
ClosureReasonModal ¤
Bases: IncidentSelectableModalMixin, SlackModal
Modal for closing an incident with a mandatory reason from early statuses.
Methods:
-
build_modal_fn–Build the closure reason modal.
-
handle_modal_fn–Handle the closure reason modal submission.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
build_modal_fn ¤
build_modal_fn(body: dict[str, Any], incident: Incident, carry_over: dict[str, Any] | None = None, **kwargs: Any) -> View
Build the closure reason modal.
carry_over lets upstream callers (Update Status modal) pass form changes that should be applied along with the closure (e.g. a priority change submitted in the same step). Values are serialized into private_metadata so they survive the round-trip to Slack.
Source code in src/firefighter/slack/views/modals/closure_reason.py
handle_modal_fn ¤
Handle the closure reason modal submission.
Source code in src/firefighter/slack/views/modals/closure_reason.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
KeyEvents ¤
Bases: MessageForm[KeyEventsTimelineForm]
Methods:
-
handle_modal_fn–Handle the time and date inputs for the key events.
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
open_shortcut class-attribute instance-attribute ¤
open_shortcut: str | None = None
Slack shortcut to open the modal.
handle_modal_fn ¤
Handle the time and date inputs for the key events.
Source code in src/firefighter/slack/views/modals/key_event_message.py
OnCallModal ¤
Bases: IncidentSelectableModalMixin, SlackModal
Methods:
-
build_modal_fn–XXX Should get an incident ID instead of an incident.
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
open_shortcut class-attribute instance-attribute ¤
open_shortcut: str | None = None
Slack shortcut to open the modal.
build_modal_fn ¤
XXX Should get an incident ID instead of an incident.
Source code in src/firefighter/slack/views/modals/trigger_oncall.py
OpenModal ¤
Bases: SlackModal
Methods:
-
get_details_modal_form_class–Get the details modal form class based on the incident type.
-
handle_modal_fn–Handle response from /incident open modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
get_details_modal_form_class staticmethod ¤
get_details_modal_form_class(open_incident_context: OpeningData, incident_type_value: str | None) -> type[SetIncidentDetails[Any]] | None
Get the details modal form class based on the incident type.
Returns None if no incident type is selected.
Source code in src/firefighter/slack/views/modals/open.py
handle_modal_fn ¤
Handle response from /incident open modal.
Source code in src/firefighter/slack/views/modals/open.py
SlackMessageReviewTimeline ¤
SlackMessageReviewTimeline(incident: Incident, carry_over_payload: str | None = None, resolution: str | None = None)
Bases: SlackMessageSurface
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/views/modals/review_timeline.py
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
UpdateModal ¤
Bases: IncidentSelectableModalMixin, SlackModal
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
open_shortcut class-attribute instance-attribute ¤
open_shortcut: str | None = None
Slack shortcut to open the modal.
events ¤
Modules:
-
actions_and_shortcuts– -
commands– -
member_joined_channel– -
member_left_channel– -
message– -
reaction_added–
Functions:
-
handle_message_events_ignore–Ignore other message events.
handle_message_events_ignore ¤
Ignore other message events. Must be the last event handler for message.
actions_and_shortcuts ¤
Functions:
-
open_link–Does nothing. ack() is mandatory, even on buttons that open a URL.
-
update_update_modal–Reacts to the selection of an incident, in the select modal.
open_link ¤
update_update_modal ¤
Reacts to the selection of an incident, in the select modal.
Source code in src/firefighter/slack/views/events/actions_and_shortcuts.py
commands ¤
Functions:
-
register_commands–Register the command with its aliases.
Attributes:
-
SLACK_BUILTIN_COMMANDS–List of all Slack built-in commands (https://slack.com/help/articles/201259356 checked August 2022)
SLACK_BUILTIN_COMMANDS module-attribute ¤
SLACK_BUILTIN_COMMANDS = (
"/archive",
"/call",
"/collapse",
"/dm",
"/expand",
"/feed",
"/invite",
"/leave",
"/msg",
"/remind",
"/remove",
"/rename",
"/search",
"/shrug",
"/status",
"/topic",
)
List of all Slack built-in commands (https://slack.com/help/articles/201259356 checked August 2022)
register_commands ¤
Register the command with its aliases. Commands are checked: - Fix commands that does not start with a slash, contain spaces, uppercase characters or are longer than 32 characters. - Ignore commands which names are built-in Slack commands.
⚠️ Don't forget to add the command and its aliases on your Slack App settings.
Source code in src/firefighter/slack/views/events/commands.py
member_joined_channel ¤
Functions:
-
member_joined_channel–When a user joins a channel, we add it to the list of conversations.
member_joined_channel ¤
When a user joins a channel, we add it to the list of conversations.
API Reference: https://api.slack.com/events/member_joined_channel
Source code in src/firefighter/slack/views/events/member_joined_channel.py
member_left_channel ¤
Functions:
-
member_left_channel–When a user leaves a channel, we remove it from the list of conversations.
member_left_channel ¤
When a user leaves a channel, we remove it from the list of conversations.
API Reference: https://api.slack.com/events/member_left_channel
Source code in src/firefighter/slack/views/events/member_left_channel.py
message ¤
Functions:
-
handle_message_events_ignore–Ignore other message events.
handle_message_events_ignore ¤
Ignore other message events. Must be the last event handler for message.
reaction_added ¤
Functions:
-
reaction_added_ignore–Ignore other reaction_added events.
reaction_added_ignore ¤
Ignore other reaction_added events. Must be the last event handler for reaction_added.
modals ¤
Modules:
-
base_modal– -
close– -
closure_reason– -
key_event_message– -
open– -
opening– -
postmortem– -
review_timeline–Timeline review checkpoint shown before an incident moves to Post-mortem.
-
timeline_preview–One small, shared rendering of the seven key events, for every Slack surface.
-
trigger_oncall– -
update– -
utils–Utilities for modal handling to avoid circular imports.
base_modal ¤
Modules:
-
base– -
form_utils–
base ¤
Classes:
-
MessageForm–Form wrapper to use a Django form in a Slack message.
-
ModalForm–Specific SlackModal to handle a Django form.
-
SlackModal–Two main responsibilities:
MessageForm ¤
Bases: SlackModal
Form wrapper to use a Django form in a Slack message.
Provided a Django form in form_class, it will handle: - generation of Slack Blocks - validation and submission of the form
Attributes:
-
callback_id(str | Pattern[str]) –Callback ID for the Slack View
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
ModalForm ¤
Bases: SlackModal
Specific SlackModal to handle a Django form.
Provided a Django form in form_class, it will handle: - generation of Slack Blocks - validation and submission of the form
Attributes:
-
callback_id(str | Pattern[str]) –Callback ID for the Slack View
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
SlackModal ¤
Two main responsibilities: - Register the modal on Slack to open it with shortcuts or actions - Provide useful context for build_modal_fn and handle_modal_fn, such as body, incident, user, etc.
Attributes:
-
callback_id(str | Pattern[str]) –Callback ID for the Slack View
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
form_utils ¤
Classes:
-
SafeOption–Make sure we are creating valid Option, warn otherwise.
-
SlackForm– -
SlackFormJSONEncoder–JSON encoder that can handle UUIDs and Django models.
Functions:
-
slack_view_submission_to_dict–Returns a dict of the form data from a Slack view submission.
SafeOption ¤
SafeOption(
*,
value: str,
label: str | None = None,
text: str | dict[str, Any] | TextObject | None = None,
description: str | dict[str, Any] | TextObject | None = None,
url: str | None = None,
**others: dict[str, Any]
)
Bases: Option
Make sure we are creating valid Option, warn otherwise.
Source code in src/firefighter/slack/views/modals/base_modal/form_utils.py
SlackForm ¤
SlackForm(form: type[T], slack_fields: SlackFormAttributesDict | None = None)
Methods:
-
slack_blocks–Return the list of blocks from a SlackForm.
Source code in src/firefighter/slack/views/modals/base_modal/form_utils.py
slack_blocks ¤slack_blocks(block_wrapper: Literal['section_accessory', 'input', 'action'] = 'input') -> list[Block]
Return the list of blocks from a SlackForm.
Parameters:
-
block_wrapper(str, default:'input') –Type of blocks destination. Defaults to "input".
Raises:
-
ValueError–Raised if one of the initial value does not match the field type.
Returns:
-
list[Block]–list[Block]: The List of Slack Blocks.
Source code in src/firefighter/slack/views/modals/base_modal/form_utils.py
SlackFormJSONEncoder ¤
Bases: JSONEncoder
JSON encoder that can handle UUIDs and Django models. Used to serialize the form data to JSON for Slack modal private_metadata.
slack_view_submission_to_dict ¤
Returns a dict of the form data from a Slack view submission.
Source code in src/firefighter/slack/views/modals/base_modal/form_utils.py
close ¤
Classes:
CloseModal ¤
Bases: IncidentSelectableModalMixin, ModalForm[CloseIncidentFormSlack]
Methods:
-
handle_modal_fn–Handle response from /incident close modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
handle_modal_fn ¤
Handle response from /incident close modal.
Source code in src/firefighter/slack/views/modals/close.py
closure_reason ¤
Classes:
-
ClosureReasonModal–Modal for closing an incident with a mandatory reason from early statuses.
ClosureReasonModal ¤
Bases: IncidentSelectableModalMixin, SlackModal
Modal for closing an incident with a mandatory reason from early statuses.
Methods:
-
build_modal_fn–Build the closure reason modal.
-
handle_modal_fn–Handle the closure reason modal submission.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
build_modal_fn ¤
build_modal_fn(body: dict[str, Any], incident: Incident, carry_over: dict[str, Any] | None = None, **kwargs: Any) -> View
Build the closure reason modal.
carry_over lets upstream callers (Update Status modal) pass form changes that should be applied along with the closure (e.g. a priority change submitted in the same step). Values are serialized into private_metadata so they survive the round-trip to Slack.
Source code in src/firefighter/slack/views/modals/closure_reason.py
handle_modal_fn ¤
Handle the closure reason modal submission.
Source code in src/firefighter/slack/views/modals/closure_reason.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
key_event_message ¤
Classes:
KeyEvents ¤
Bases: MessageForm[KeyEventsTimelineForm]
Methods:
-
handle_modal_fn–Handle the time and date inputs for the key events.
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
open_shortcut class-attribute instance-attribute ¤
open_shortcut: str | None = None
Slack shortcut to open the modal.
handle_modal_fn ¤
Handle the time and date inputs for the key events.
Source code in src/firefighter/slack/views/modals/key_event_message.py
open ¤
Classes:
OpenModal ¤
Bases: SlackModal
Methods:
-
get_details_modal_form_class–Get the details modal form class based on the incident type.
-
handle_modal_fn–Handle response from /incident open modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
get_details_modal_form_class staticmethod ¤
get_details_modal_form_class(open_incident_context: OpeningData, incident_type_value: str | None) -> type[SetIncidentDetails[Any]] | None
Get the details modal form class based on the incident type.
Returns None if no incident type is selected.
Source code in src/firefighter/slack/views/modals/open.py
handle_modal_fn ¤
Handle response from /incident open modal.
Source code in src/firefighter/slack/views/modals/open.py
opening ¤
Modules:
-
details– -
select_impact– -
set_details–
details ¤
Modules:
-
unified–
unified ¤
Classes:
-
OpeningUnifiedModal–Unified modal for all incident types (P1-P5).
-
UnifiedIncidentFormSlack–Slack version of UnifiedIncidentForm with Slack-specific field configurations.
OpeningUnifiedModal ¤ Bases: SetIncidentDetails[UnifiedIncidentFormSlack]
Unified modal for all incident types (P1-P5).
Methods:
-
build_modal_fn–Build modal with impact-aware form.
-
get_form_class–Return a SlackForm wrapper that passes impacts_data and response_type.
-
handle_modal_fn–Handle response from /incident open modal.
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/opening/set_details.py
open_shortcut class-attribute instance-attribute ¤open_shortcut: str | None = None
Slack shortcut to open the modal.
build_modal_fn ¤Build modal with impact-aware form.
Source code in src/firefighter/slack/views/modals/opening/details/unified.py
get_form_class ¤get_form_class() -> Any
Return a SlackForm wrapper that passes impacts_data and response_type.
Source code in src/firefighter/slack/views/modals/opening/details/unified.py
handle_modal_fn ¤Handle response from /incident open modal.
Source code in src/firefighter/slack/views/modals/opening/set_details.py
UnifiedIncidentFormSlack ¤UnifiedIncidentFormSlack(*args: Any, impacts_data: dict[str, Any] | None = None, response_type: str = 'critical', **kwargs: Any)
Bases: UnifiedIncidentForm
Slack version of UnifiedIncidentForm with Slack-specific field configurations.
Parameters:
-
*args(Any, default:()) –Positional arguments passed to parent form
-
impacts_data(dict[str, Any] | None, default:None) –Dictionary of impact selections
-
response_type(str, default:'critical') –"critical" or "normal"
-
**kwargs(Any, default:{}) –Keyword arguments passed to parent form
Methods:
-
clean–Custom validation based on response type and impacts.
-
get_visible_fields_for_impacts–Determine which fields should be visible based on impacts and response type.
-
trigger_incident_workflow–Trigger unified incident workflow for all priorities.
Source code in src/firefighter/slack/views/modals/opening/details/unified.py
clean ¤Custom validation based on response type and impacts.
Source code in src/firefighter/incidents/forms/unified_incident.py
get_visible_fields_for_impacts ¤get_visible_fields_for_impacts(impacts_data: dict[str, ImpactLevel | str], response_type: str) -> list[str]
Determine which fields should be visible based on impacts and response type.
Parameters:
-
impacts_data(dict[str, ImpactLevel | str]) –Dictionary of impact type → impact level (ImpactLevel object or UUID string)
-
response_type(str) –"critical" or "normal"
Returns:
Source code in src/firefighter/incidents/forms/unified_incident.py
trigger_incident_workflow ¤trigger_incident_workflow(
creator: User, impacts_data: dict[str, ImpactLevel], response_type: str = "critical", *args: Any, **kwargs: Any
) -> Incident
Trigger unified incident workflow for all priorities.
This unified workflow: 1. Always creates an Incident in the database (P1-P5) 2. Conditionally creates a Slack channel (P1-P3 only) 3. Always creates a Jira ticket linked to the Incident (P1-P5)
Parameters:
-
creator(User) –User creating the incident
-
impacts_data(dict[str, ImpactLevel]) –Dictionary of impact data
-
response_type(str, default:'critical') –"critical" (P1-P3) or "normal" (P4-P5)
-
*args(Any, default:()) –Additional positional arguments (unused)
-
**kwargs(Any, default:{}) –Additional keyword arguments (unused)
Returns:
-
Incident–The created Incident object
Source code in src/firefighter/incidents/forms/unified_incident.py
select_impact ¤
Classes:
-
SelectImpactModal–TODO: The detailed impacts selected should be saved on the incident.
SelectImpactModal ¤
Bases: IncidentSelectableModalMixin, ModalForm[SelectImpactFormSlack]
TODO: The detailed impacts selected should be saved on the incident.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
set_details ¤
Classes:
SetIncidentDetails ¤
Bases: ModalForm[T]
Methods:
-
handle_modal_fn–Handle response from /incident open modal.
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/opening/set_details.py
open_shortcut class-attribute instance-attribute ¤open_shortcut: str | None = None
Slack shortcut to open the modal.
handle_modal_fn ¤Handle response from /incident open modal.
Source code in src/firefighter/slack/views/modals/opening/set_details.py
postmortem ¤
Functions:
-
handle_create_postmortem_action–Create post-mortem(s) on demand from the modal (e.g. P3+ incidents).
handle_create_postmortem_action ¤
Create post-mortem(s) on demand from the modal (e.g. P3+ incidents).
Source code in src/firefighter/slack/views/modals/postmortem.py
review_timeline ¤
Timeline review checkpoint shown before an incident moves to Post-mortem.
This does not change how the timeline is recorded today - every status change still comes from the normal Update Status modal. It only inserts a confirmation step right before the Post-mortem transition, showing the timeline as already recorded and letting a human accept it (the transition then proceeds normally, and the confirmed timeline is pushed into the incident's Jira post-mortem "Timeline" field, if any) or reject it (the transition is cancelled, and a correction message - same pattern as the Key Events message - lets the human edit the recorded times directly, each change saving immediately).
Accepting is not the end of it: a timeline is often found wrong after the fact. The correction message can be reopened from the accepted review message and from the Update menu, and re-checking it then re-syncs the post-mortem and the metrics instead of transitioning a second time.
Classes:
-
SlackMessageReviewTimeline– -
TimelineCorrection–Correction message, same pattern as Key Events: edit a field, it saves immediately.
Functions:
-
build_carry_over_payload–Serialize the incident id and carried-over form fields into a button value.
-
can_correct_timeline–Whether the timeline of this incident is still open to corrections.
-
handle_open_timeline_correction–Open the correction form from the Update menu, outside any review cycle.
-
handle_review_timeline_correct–Reopen the correction form from a resolved review message.
-
handle_review_timeline_recheck–Re-run the checks from the correction message, then transition or re-sync.
-
post_timeline_correction–Post a fresh correction message in the incident channel.
SlackMessageReviewTimeline ¤
SlackMessageReviewTimeline(incident: Incident, carry_over_payload: str | None = None, resolution: str | None = None)
Bases: SlackMessageSurface
Methods:
-
get_metadata–The value of
event_typeshould be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the patternand -
post_message–Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/views/modals/review_timeline.py
get_metadata ¤
The value of event_type should be an alphanumeric string, and human-readable. The value of this field may appear in the UI to developers, so keep this in mind when choosing a value. Developers should make an effort to name with the pattern
Returns:
-
Metadata(Metadata) –Slack Metadata for the message.
Source code in src/firefighter/slack/messages/base.py
post_message ¤
post_message(conversation_id: str, client: WebClient = DefaultWebClient, **kwargs: Never) -> SlackResponse
Deprecated. Only use for Global Channel, until the global channel is set in DB.
Source code in src/firefighter/slack/messages/base.py
TimelineCorrection ¤
Bases: MessageForm[IncidentTimelineForm]
Correction message, same pattern as Key Events: edit a field, it saves immediately.
Chosen over a modal because a modal's fixed height makes many fields (2 milestones + one per status reached) cramped and scroll-heavy; a channel message doesn't have that constraint and matches a surface users are already familiar with.
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
open_shortcut class-attribute instance-attribute ¤
open_shortcut: str | None = None
Slack shortcut to open the modal.
build_carry_over_payload ¤
Serialize the incident id and carried-over form fields into a button value.
Source code in src/firefighter/slack/views/modals/review_timeline.py
can_correct_timeline ¤
Whether the timeline of this incident is still open to corrections.
A closed incident is out: its metrics are consolidated and its post-mortem is out of FireFighter's hands, so a late edit would silently disagree with what has already been reported. Those corrections go through the admin, deliberately.
Source code in src/firefighter/slack/views/modals/review_timeline.py
handle_open_timeline_correction ¤
Open the correction form from the Update menu, outside any review cycle.
The form is a channel message, not a modal (see TimelineCorrection), so the modal that was clicked from reports where the message went instead of hosting the form itself.
Source code in src/firefighter/slack/views/modals/review_timeline.py
handle_review_timeline_correct ¤
Reopen the correction form from a resolved review message.
Source code in src/firefighter/slack/views/modals/review_timeline.py
handle_review_timeline_recheck ¤
Re-run the checks from the correction message, then transition or re-sync.
Saves a round trip through the Update Status modal once the times are fixed. The transition it applies carries the status only: the message and any priority or category change from the original submission cannot be threaded across the correction step, so nothing pretends to carry them.
Source code in src/firefighter/slack/views/modals/review_timeline.py
post_timeline_correction ¤
post_timeline_correction(incident: Incident) -> None
Post a fresh correction message in the incident channel.
REPLACE, not UPDATE: a new correction cycle removes the stale message from a previous one rather than editing it in place, wherever it was buried. Editing a single field within the same cycle (TimelineCorrection.update_with_form) still updates in place.
Source code in src/firefighter/slack/views/modals/review_timeline.py
timeline_preview ¤
One small, shared rendering of the seven key events, for every Slack surface.
The Key Events message, the timeline correction message and the Post-mortem review checkpoint all describe the same timeline. They used to describe it differently (or not at all), so a reviewer had to open a third surface to see what their edit had just done. They now share this preview: one line, always the seven canonical steps, unrecorded ones shown as a dash rather than hidden - so the shape of the line stays the same as it fills in.
Functions:
-
timeline_chain–The seven steps as one wrapping line: emoji, label, time.
-
timeline_preview_blocks–Compact preview: one line for the timeline, one line if it has issues.
-
timeline_span–Whether every recorded step falls on one day, and the span to display.
timeline_chain ¤
timeline_chain(steps: Collection[TimelineStep], *, single_day: bool, flagged: Collection[str] = (), with_labels: bool = True) -> str
The seven steps as one wrapping line: emoji, label, time.
Minute precision keeps the line short - exact seconds live in the issue messages and in the correction fields. with_labels=False drops the step names for the smallest possible rendering, for surfaces that already spell the steps out underneath (the correction form's own fields).
Source code in src/firefighter/slack/views/modals/timeline_preview.py
timeline_preview_blocks ¤
Compact preview: one line for the timeline, one line if it has issues.
Deliberately two blocks at most. It sits on top of forms that people are filling in, and every field they edit re-renders the message it lives in - a preview that grows with the incident would push the fields off screen.
Source code in src/firefighter/slack/views/modals/timeline_preview.py
timeline_span ¤
timeline_span(steps: Collection[TimelineStep]) -> tuple[bool, str | None]
Whether every recorded step falls on one day, and the span to display.
Incidents can run over several days, so the date is never dropped: on a single day it goes in the heading and the steps carry times only, otherwise each step carries its own day.
Source code in src/firefighter/slack/views/modals/timeline_preview.py
trigger_oncall ¤
Classes:
OnCallModal ¤
Bases: IncidentSelectableModalMixin, SlackModal
Methods:
-
build_modal_fn–XXX Should get an incident ID instead of an incident.
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
open_shortcut class-attribute instance-attribute ¤
open_shortcut: str | None = None
Slack shortcut to open the modal.
build_modal_fn ¤
XXX Should get an incident ID instead of an incident.
Source code in src/firefighter/slack/views/modals/trigger_oncall.py
update ¤
Classes:
UpdateModal ¤
Bases: IncidentSelectableModalMixin, SlackModal
Attributes:
-
open_shortcut(str | None) –Slack shortcut to open the modal.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
open_shortcut class-attribute instance-attribute ¤
open_shortcut: str | None = None
Slack shortcut to open the modal.
utils ¤
Utilities for modal handling to avoid circular imports.
Functions:
-
get_close_modal_view–Get the appropriate modal view for closing an incident.
-
handle_close_modal_callback–Handle modal callback, delegating to closure reason modal if needed.
-
handle_update_status_close_request–Handle update status request to close incident, showing reason modal if needed.
-
show_timeline_review–Show a timeline review checkpoint before moving an incident to Post-mortem.
get_close_modal_view ¤
Get the appropriate modal view for closing an incident.
This function determines whether to show the closure reason modal or delegate to the normal close modal.
Source code in src/firefighter/slack/views/modals/utils.py
handle_close_modal_callback ¤
handle_close_modal_callback(ack: Any, body: dict[str, Any], incident: Incident, user: Any) -> bool | None
Handle modal callback, delegating to closure reason modal if needed.
Source code in src/firefighter/slack/views/modals/utils.py
handle_update_status_close_request ¤
handle_update_status_close_request(
ack: Any, body: dict[str, Any], incident: Incident, target_status: IncidentStatus, form: Form | None = None
) -> bool
Handle update status request to close incident, showing reason modal if needed.
When the closure reason modal is pushed on top of the Update Status modal, the Update Status submission is dropped by Slack. Any fields that were changed alongside the status (priority, incident_category, ...) would be silently lost. To avoid that, we collect those changes from the form and pass them as carry-over data so the closure reason modal can re-apply them on submission.
Returns True if the request was handled (reason modal shown), False otherwise.
Source code in src/firefighter/slack/views/modals/utils.py
show_timeline_review ¤
Show a timeline review checkpoint before moving an incident to Post-mortem.
Acks the modal submission and posts a review message with the timeline recorded so far, instead of applying the Post-mortem transition immediately. The transition only happens if the human accepts it from that message.
Source code in src/firefighter/slack/views/modals/utils.py
select_impact ¤
Classes:
-
SelectImpactModal–TODO: The detailed impacts selected should be saved on the incident.
SelectImpactModal ¤
Bases: IncidentSelectableModalMixin, ModalForm[SelectImpactFormSlack]
TODO: The detailed impacts selected should be saved on the incident.
Source code in src/firefighter/slack/views/modals/base_modal/base.py
views ¤
Classes:
-
SlackEventsHandler–Handle all Slack events.
SlackEventsHandler ¤
Bases: View
Handle all Slack events.