RAID Module¤
The RAID module provides enhanced Jira integration for incident management and external ticket creation.
Overview¤
RAID (Request And Issue Database) extends FireFighter's capabilities with:
- Automatic Jira ticket creation for incidents
- External API for ticket creation (Landbot integration)
- Smart user resolution based on email domains
- Priority mapping from P1-P5 to Jira priorities
- Attachment handling for external submissions
- Slack notifications for ticket updates
Priority Mapping¤
The RAID module supports full P1-P5 priority mapping:
| Priority | Level | Jira Priority | Use Case |
|---|---|---|---|
| P1 | Critical | 1 | System outages, complete service failures |
| P2 | High | 2 | Major functionality impaired, significant impact |
| P3 | Medium | 3 | Minor functionality affected, moderate impact |
| P4 | Low | 4 | Small issues, minimal impact |
| P5 | Lowest | 5 | Cosmetic issues, enhancement requests |
User Resolution¤
The module handles user resolution for external ticket creation:
- Internal users: Direct mapping from email to existing users
- External users: Email domain-based routing to default Jira users
- Slack fallback: Attempts to find users via Slack integration
- Default assignment: Falls back to configured default Jira user
API Reference¤
raid ¤
RAID is ManoMano's internal issue dispatcher.
It works with Slack and Jira to create, update and close issues.
It is currently not configurable.
Modules:
client ¤
Classes:
RaidJiraClient ¤
Bases: JiraClient
Methods:
-
add_attachments_to_issue–Add attachments to a Jira issue.
-
assign_issue–Assign a Jira issue to a user.
-
create_postmortem_issue–Create a Jira post-mortem issue with custom fields.
-
get_jira_user_from_jira_id–Look for a Jira User in DB, if not found, fetch it from Jira API.
-
get_jira_user_from_user–Fetches a Jira user from the Jira API.
-
get_watchers_from_jira_ticket–Fetch watchers for a specific Jira ticket from Jira API.
-
transition_issue_auto–Attempts to close an issue by applying transitions to it.
-
update_issue_fields–Update Jira issue fields (supports custom fields like customfield_11064).
Source code in src/firefighter/jira_app/client.py
add_attachments_to_issue staticmethod ¤
Add attachments to a Jira issue.
Parameters:
Raises:
-
JiraAttachmentError–if there is an error while adding any attachment
Source code in src/firefighter/raid/client.py
assign_issue ¤
Assign a Jira issue to a user.
Parameters:
-
issue_key(str) –Jira issue key (e.g., "INCIDENT-123")
-
account_id(str) –Jira account ID of the user
Returns:
-
bool–True if assignment succeeded, False otherwise
Note
This method does not raise exceptions. Assignment failures are logged as warnings since assignment is typically an optional operation.
Source code in src/firefighter/jira_app/client.py
create_postmortem_issue ¤
create_postmortem_issue(project_key: str, issue_type: str, fields: dict[str, Any], parent_issue_key: str | None = None) -> dict[str, Any]
Create a Jira post-mortem issue with custom fields.
Parameters:
-
project_key(str) –Jira project key (e.g., "INCIDENT")
-
issue_type(str) –Issue type name (e.g., "Post-mortem")
-
fields(dict[str, Any]) –Dictionary of field IDs to values
-
parent_issue_key(str | None, default:None) –Optional parent issue key to link this post-mortem to
Returns:
Raises:
-
JiraAPIError–If issue creation fails
Source code in src/firefighter/jira_app/client.py
get_jira_user_from_jira_id ¤
Look for a Jira User in DB, if not found, fetch it from Jira API.
Parameters:
-
jira_account_id(str) –Jira account id
Raises:
-
JiraUserNotFoundError–User not found in Jira nor in DB
-
JiraUserDatabaseError–Unable to create user in DB
-
ValueError–Empty jira_account_id
Returns:
-
JiraUser(JiraUser) –Jira user object
Source code in src/firefighter/jira_app/client.py
get_jira_user_from_user ¤
Fetches a Jira user from the Jira API.
Parameters:
-
user(User) –User object
Raises:
-
JiraUserNotFoundError–User not found in Jira
Returns:
-
JiraAPIUser(JiraUser) –Jira API user object
Source code in src/firefighter/jira_app/client.py
get_watchers_from_jira_ticket ¤
Fetch watchers for a specific Jira ticket from Jira API.
Parameters:
Raises:
-
ValueError–Empty issue id
Returns:
-
list(User) –List of Jira users object, or empty list if ticket doesn't exist
Source code in src/firefighter/jira_app/client.py
transition_issue_auto ¤
Attempts to close an issue by applying transitions to it.
Parameters:
-
issue_id(str | int) –Jira issue id
-
target_status_name(str) –target status name
-
workflow_name(str) –workflow name
Source code in src/firefighter/jira_app/client.py
update_issue_fields ¤
Update Jira issue fields (supports custom fields like customfield_11064).
forms ¤
Functions:
-
prepare_jira_fields–Prepare all fields for jira_client.create_issue().
prepare_jira_fields ¤
prepare_jira_fields(
*,
title: str,
description: str,
priority: int,
reporter: str,
incident_category: str,
environments: list[str],
platforms: list[str],
impacts_data: dict[str, ImpactLevel],
optional_fields: dict[str, Any] | None = None
) -> dict[str, Any]
Prepare all fields for jira_client.create_issue().
This function centralizes Jira field preparation for both P1-P3 and P4-P5 incidents, ensuring all custom fields are properly passed.
Parameters:
-
title(str) –Incident title
-
description(str) –Incident description
-
priority(int) –Priority value (1-5)
-
reporter(str) –Jira user account ID
-
incident_category(str) –Category name
-
environments(list[str]) –List of environment values (e.g. ["PRD", "STG"])
-
platforms(list[str]) –List of platform values (e.g. ["platform-FR", "platform-DE"])
-
impacts_data(dict[str, ImpactLevel]) –Dictionary of impact data for business_impact computation
-
optional_fields(dict[str, Any] | None, default:None) –Optional dictionary containing: - zendesk_ticket_id: Zendesk ticket ID (customer-specific) - seller_contract_id: Seller contract ID (seller-specific) - zoho_desk_ticket_id: Zoho Desk ticket ID (seller-specific) - is_key_account: Key account flag (seller-specific) - is_seller_in_golden_list: Golden list flag (seller-specific) - suggested_team_routing: Suggested team routing (P4-P5 only)
Returns:
Source code in src/firefighter/raid/forms.py
models ¤
serializers ¤
Classes:
Functions:
-
validate_no_spaces–Ensure the string does not contain spaces.
LandbotIssueRequestSerializer ¤
Bases: ModelSerializer[JiraTicket]
Methods:
-
validate_labels–Transform null labels to empty list.
validate_labels ¤
service ¤
Classes:
-
CustomerIssueData–Data container for customer issue creation parameters.
Functions:
-
check_issue_id–Check and return the issue ID from a JiraObject.
-
create_issue_customer–Creates a Jira Incident issue of type Customer.
-
create_issue_documentation_request–Creates a Jira issue of type Documentation/Process Request.
-
create_issue_feature_request–Creates a Jira issue of type Feature Request.
-
create_issue_internal–Creates a Jira Incident Issue of type Internal.
-
create_issue_seller–Creates a Jira Incident issue of type Seller.
-
get_jira_user_from_user–Returns the JiraUser object for a given user, if it exists in DB or can be fetched on Jira API. Returns the default JiraUser if not found.
CustomerIssueData dataclass ¤
CustomerIssueData(
priority: int | None,
labels: list[str] | None,
platform: str,
business_impact: str | None,
team_to_be_routed: str | None,
area: str | None,
zendesk_ticket_id: str | None,
incident_category: str | None = None,
)
Data container for customer issue creation parameters.
check_issue_id ¤
Check and return the issue ID from a JiraObject.
Raises JiraAPIError if the issue ID is missing or invalid.
Source code in src/firefighter/raid/service.py
create_issue_customer ¤
create_issue_customer(title: str, description: str, reporter: str, issue_data: CustomerIssueData) -> JiraObject
Creates a Jira Incident issue of type Customer.
Parameters:
-
title(str) –Summary of the issue
-
description(str) –Description of the issue
-
reporter(str) –Jira account id of the reporter
-
issue_data(CustomerIssueData) –Container with issue parameters
Source code in src/firefighter/raid/service.py
create_issue_documentation_request ¤
create_issue_documentation_request(
title: str, description: str, reporter: str, priority: int | None, labels: list[str] | None, platform: str
) -> JiraObject
Creates a Jira issue of type Documentation/Process Request.
Parameters:
-
title(str) –Summary of the issue
-
description(str) –Description of the issue
-
reporter(str) –Jira account id of the reporter
-
priority(int) –Priority of the issue
-
labels(list[str]) –Labels to add to the issue
-
platform(str) –Platform of the issue
Source code in src/firefighter/raid/service.py
create_issue_feature_request ¤
create_issue_feature_request(
title: str, description: str, reporter: str, priority: int | None, labels: list[str] | None, platform: str
) -> JiraObject
Creates a Jira issue of type Feature Request.
Parameters:
-
title(str) –Summary of the issue
-
description(str) –Description of the issue
-
reporter(str) –Jira account id of the reporter
-
priority(int) –Priority of the issue
-
labels(list[str]) –Labels to add to the issue
-
platform(str) –Platform of the issue
Source code in src/firefighter/raid/service.py
create_issue_internal ¤
create_issue_internal(
title: str,
description: str,
reporter: str,
priority: int | None,
labels: list[str] | None,
platform: str,
business_impact: str | None,
team_to_be_routed: str | None,
incident_category: str | None,
) -> JiraObject
Creates a Jira Incident Issue of type Internal.
Parameters:
-
title(str) –Summary of the issue
-
description(str) –Description of the issue
-
reporter(str) –Jira account id of the reporter
-
priority(int) –Priority of the issue
-
labels(list[str]) –Labels to add to the issue
-
platform(str) –Platform of the issue
-
business_impact(str) –Business impact of the issue
-
team_to_be_routed(str) –Team to be routed
-
incident_category(str) –Incident category of the issue
Source code in src/firefighter/raid/service.py
create_issue_seller ¤
create_issue_seller(
title: str,
description: str,
reporter: str,
priority: int | None,
labels: list[str] | None,
platform: str,
business_impact: str | None,
team_to_be_routed: str | None,
incident_category: str | None,
seller_contract_id: str | None,
is_key_account: bool | None,
is_seller_in_golden_list: bool | None,
zoho_desk_ticket_id: str | None,
) -> JiraObject
Creates a Jira Incident issue of type Seller.
Parameters:
-
title(str) –Summary of the issue
-
description(str) –Description of the issue
-
reporter(str) –Jira account id of the reporter
-
priority(int) –Priority of the issue
-
labels(list[str]) –Labels to add to the issue
-
platform(str) –Platform of the issue
-
business_impact(str) –Business impact of the issue
-
team_to_be_routed(str) –Team to be routed
-
incident_category(str) –Incident category of the issue
-
seller_contract_id(str) –Seller contract id
-
is_key_account(bool) –Is key account
-
is_seller_in_golden_list(bool) –Is seller in golden list
-
zoho_desk_ticket_id(str) –Zoho desk ticket id
Source code in src/firefighter/raid/service.py
get_jira_user_from_user ¤
Returns the JiraUser object for a given user, if it exists in DB or can be fetched on Jira API. Returns the default JiraUser if not found.
Source code in src/firefighter/raid/service.py
signals ¤
Modules:
incident_updated ¤
Functions:
-
incident_priority_post_save_fallback–Fallback to push priority to Jira when Incident saves with priority_id in update_fields
-
incident_status_post_save_fallback–Fallback to push status to Jira when Incident saves with status in update_fields
-
incident_updated_close_ticket_when_mitigated_or_postmortem–Close Jira incident ticket based on incident status and priority.
-
incident_updated_sync_priority_to_jira–Push Impact priority changes to Jira custom priority field (customfield_11064).
incident_priority_post_save_fallback ¤
incident_priority_post_save_fallback(
sender: Any, instance: Incident, *, created: bool, update_fields: set[str] | None, **kwargs: Any
) -> None
Fallback to push priority to Jira when Incident saves with priority_id in update_fields but no incident_updated signal fired (e.g., admin edits). Skips when marked to avoid loops.
Source code in src/firefighter/raid/signals/incident_updated.py
incident_status_post_save_fallback ¤
incident_status_post_save_fallback(
sender: Any, instance: Incident, *, created: bool, update_fields: set[str] | None, **kwargs: Any
) -> None
Fallback to push status to Jira when Incident saves with status in update_fields but no incident_updated signal fired (e.g., admin edits). Skips when marked to avoid loops.
Source code in src/firefighter/raid/signals/incident_updated.py
incident_updated_close_ticket_when_mitigated_or_postmortem ¤
incident_updated_close_ticket_when_mitigated_or_postmortem(
sender: Any, incident: Incident, incident_update: IncidentUpdate, updated_fields: list[str], **kwargs: Any
) -> None
Close Jira incident ticket based on incident status and priority.
Closure logic: - P1/P2 (needs_postmortem): Close only when incident is CLOSED - P3+ (no postmortem): Close when incident is MITIGATED or CLOSED - POST_MORTEM status never closes the ticket (it remains open during PM phase)
Source code in src/firefighter/raid/signals/incident_updated.py
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 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 | |
incident_updated_sync_priority_to_jira ¤
incident_updated_sync_priority_to_jira(
sender: Any, incident: Incident, incident_update: IncidentUpdate, updated_fields: list[str], **kwargs: Any
) -> None
Push Impact priority changes to Jira custom priority field (customfield_11064). Skips if change originated from Jira (event_type='jira_priority_sync') to avoid loops.
Source code in src/firefighter/raid/signals/incident_updated.py
utils ¤
Functions:
-
get_domain_from_email–Returns the domain from an email address.
-
normalize_cache_value–Normalize cache values for loop-prevention keys.
get_domain_from_email cached ¤
Returns the domain from an email address.
Removes any subdomain(s) and the @, applies .lower().
Parameters:
-
email(str) –The email address to extract the domain from.
Returns:
-
str–The domain part of the email address.
Raises:
-
ValueError–If the email is not well-formed.
Examples:
john.doe@example.com=>example.comalice.bob@test.example.ORG=>example.orgwebmaster@localhost=>localhost
Source code in src/firefighter/raid/utils.py
normalize_cache_value ¤
Normalize cache values for loop-prevention keys.
Source code in src/firefighter/raid/utils.py
views ¤
Classes:
CreateJiraBotView ¤
Bases: CreateModelMixin, GenericAPIView[JiraTicket]
Methods:
-
post–Allow to create a Jira ticket through Landbot.
post ¤
Allow to create a Jira ticket through Landbot. Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.
Source code in src/firefighter/raid/views/__init__.py
JiraCommentAlertView ¤
Bases: CreateAPIView[Any]
Methods:
-
post–Allow to send a message in Slack when a comment in a Jira ticket is created or modified.
post ¤
Allow to send a message in Slack when a comment in a Jira ticket is created or modified. Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.
Source code in src/firefighter/raid/views/__init__.py
JiraUpdateAlertView ¤
Bases: CreateAPIView[Any]
Methods:
-
post–Allow to send a message in Slack when some fields ("Priority", "project", "description", "status") of a Jira ticket are updated.
post ¤
Allow to send a message in Slack when some fields ("Priority", "project", "description", "status") of a Jira ticket are updated. Requires a valid Bearer token, that you can create in the back-office if you have the right permissions.