firefighter-incident 0.0.13__py3-none-any.whl → 0.0.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- firefighter/_version.py +16 -3
- firefighter/api/serializers.py +17 -8
- firefighter/api/urls.py +8 -1
- firefighter/api/views/_base.py +1 -1
- firefighter/api/views/components.py +5 -5
- firefighter/api/views/incidents.py +9 -9
- firefighter/confluence/signals/incident_updated.py +2 -2
- firefighter/firefighter/settings/components/raid.py +3 -0
- firefighter/incidents/admin.py +24 -24
- firefighter/incidents/enums.py +22 -2
- firefighter/incidents/factories.py +14 -5
- firefighter/incidents/forms/close_incident.py +4 -4
- firefighter/incidents/forms/closure_reason.py +45 -0
- firefighter/incidents/forms/create_incident.py +4 -4
- firefighter/incidents/forms/unified_incident.py +406 -0
- firefighter/incidents/forms/update_status.py +91 -5
- firefighter/incidents/menus.py +2 -2
- firefighter/incidents/migrations/0005_enable_from_p1_to_p5_priority.py +7 -5
- firefighter/incidents/migrations/0009_update_sla.py +7 -5
- firefighter/incidents/migrations/0020_create_incident_category_model.py +64 -0
- firefighter/incidents/migrations/0021_copy_component_data_to_incident_category.py +57 -0
- firefighter/incidents/migrations/0022_add_incident_category_fields.py +34 -0
- firefighter/incidents/migrations/0023_populate_incident_category_references.py +57 -0
- firefighter/incidents/migrations/0024_remove_component_fields_and_model.py +26 -0
- firefighter/incidents/migrations/0025_make_incident_category_required.py +24 -0
- firefighter/incidents/migrations/0026_alter_incidentcategory_options_and_more.py +39 -0
- firefighter/incidents/migrations/0027_add_closure_fields.py +40 -0
- firefighter/incidents/migrations/0028_add_closure_reason_constraint.py +33 -0
- firefighter/incidents/migrations/0029_add_custom_fields_to_incident.py +22 -0
- firefighter/incidents/models/__init__.py +1 -1
- firefighter/incidents/models/group.py +1 -1
- firefighter/incidents/models/incident.py +47 -20
- firefighter/incidents/models/{component.py → incident_category.py} +30 -29
- firefighter/incidents/models/incident_update.py +3 -3
- firefighter/incidents/static/css/main.min.css +1 -1
- firefighter/incidents/tables.py +9 -9
- firefighter/incidents/templates/layouts/partials/incident_card.html +1 -1
- firefighter/incidents/templates/layouts/partials/incident_timeline.html +2 -2
- firefighter/incidents/templates/layouts/partials/status_pill.html +1 -1
- firefighter/incidents/templates/pages/{component_detail.html → incident_category_detail.html} +13 -13
- firefighter/incidents/templates/pages/{component_list.html → incident_category_list.html} +2 -2
- firefighter/incidents/templates/pages/incident_detail.html +3 -3
- firefighter/incidents/urls.py +6 -6
- firefighter/incidents/views/components/details.py +9 -9
- firefighter/incidents/views/components/list.py +9 -9
- firefighter/incidents/views/reports.py +5 -5
- firefighter/incidents/views/users/details.py +2 -2
- firefighter/incidents/views/views.py +7 -7
- firefighter/jira_app/client.py +1 -1
- firefighter/logging/custom_json_formatter.py +2 -1
- firefighter/pagerduty/tasks/trigger_oncall.py +1 -1
- firefighter/raid/admin.py +0 -11
- firefighter/raid/apps.py +9 -26
- firefighter/raid/client.py +5 -5
- firefighter/raid/forms.py +84 -213
- firefighter/raid/migrations/0003_delete_raidarea.py +16 -0
- firefighter/raid/models.py +2 -21
- firefighter/raid/serializers.py +5 -4
- firefighter/raid/service.py +29 -27
- firefighter/raid/signals/incident_created.py +42 -15
- firefighter/raid/signals/incident_updated.py +3 -2
- firefighter/raid/utils.py +1 -1
- firefighter/raid/views/__init__.py +1 -1
- firefighter/slack/admin.py +8 -8
- firefighter/slack/management/commands/switch_test_users.py +272 -0
- firefighter/slack/messages/slack_messages.py +24 -9
- firefighter/slack/migrations/0005_add_incident_categories_fields.py +33 -0
- firefighter/slack/migrations/0006_copy_components_to_incident_categories.py +57 -0
- firefighter/slack/migrations/0007_remove_components_fields.py +22 -0
- firefighter/slack/migrations/0008_alter_conversation_incident_categories_and_more.py +33 -0
- firefighter/slack/models/conversation.py +3 -3
- firefighter/slack/models/incident_channel.py +1 -1
- firefighter/slack/models/user.py +1 -1
- firefighter/slack/models/user_group.py +3 -3
- firefighter/slack/rules.py +2 -2
- firefighter/slack/signals/create_incident_conversation.py +6 -0
- firefighter/slack/signals/get_users.py +2 -2
- firefighter/slack/signals/incident_updated.py +8 -2
- firefighter/slack/utils.py +2 -2
- firefighter/slack/views/events/home.py +2 -2
- firefighter/slack/views/modals/__init__.py +4 -0
- firefighter/slack/views/modals/base_modal/form_utils.py +78 -0
- firefighter/slack/views/modals/close.py +18 -5
- firefighter/slack/views/modals/closure_reason.py +193 -0
- firefighter/slack/views/modals/open.py +83 -12
- firefighter/slack/views/modals/opening/check_current_incidents.py +2 -2
- firefighter/slack/views/modals/opening/details/unified.py +203 -0
- firefighter/slack/views/modals/opening/select_impact.py +5 -2
- firefighter/slack/views/modals/opening/set_details.py +3 -2
- firefighter/slack/views/modals/postmortem.py +10 -2
- firefighter/slack/views/modals/update_status.py +32 -6
- firefighter/slack/views/modals/utils.py +51 -0
- firefighter_fixtures/incidents/{components.json → incident_categories.json} +52 -52
- {firefighter_incident-0.0.13.dist-info → firefighter_incident-0.0.15.dist-info}/METADATA +2 -2
- {firefighter_incident-0.0.13.dist-info → firefighter_incident-0.0.15.dist-info}/RECORD +133 -88
- firefighter_tests/conftest.py +4 -5
- firefighter_tests/test_api/test_api_landbot.py +1 -1
- firefighter_tests/test_firefighter/test_sso.py +146 -0
- firefighter_tests/test_incidents/test_enums.py +100 -0
- firefighter_tests/test_incidents/test_forms/conftest.py +179 -0
- firefighter_tests/test_incidents/test_forms/test_closure_reason.py +91 -0
- firefighter_tests/test_incidents/test_forms/test_form_utils.py +15 -15
- firefighter_tests/test_incidents/test_forms/test_unified_incident_form.py +570 -0
- firefighter_tests/test_incidents/test_forms/test_unified_incident_form_integration.py +581 -0
- firefighter_tests/test_incidents/test_forms/test_unified_incident_form_p4_p5.py +410 -0
- firefighter_tests/test_incidents/test_forms/test_update_status_workflow.py +343 -0
- firefighter_tests/test_incidents/test_forms/test_workflow_transitions.py +167 -0
- firefighter_tests/test_incidents/test_incident_urls.py +3 -3
- firefighter_tests/test_incidents/test_models/test_incident_category.py +165 -0
- firefighter_tests/test_incidents/test_models/test_incident_model.py +70 -2
- firefighter_tests/test_raid/conftest.py +154 -0
- firefighter_tests/test_raid/test_p1_p3_jira_fields.py +372 -0
- firefighter_tests/test_raid/test_priority_mapping.py +267 -0
- firefighter_tests/test_raid/test_raid_client.py +580 -0
- firefighter_tests/test_raid/test_raid_forms.py +552 -0
- firefighter_tests/test_raid/test_raid_models.py +185 -0
- firefighter_tests/test_raid/test_raid_serializers.py +507 -0
- firefighter_tests/test_raid/test_raid_service.py +442 -0
- firefighter_tests/test_raid/test_raid_signals.py +187 -0
- firefighter_tests/test_raid/test_raid_views.py +196 -0
- firefighter_tests/test_slack/messages/__init__.py +0 -0
- firefighter_tests/test_slack/messages/test_slack_messages.py +367 -0
- firefighter_tests/test_slack/views/modals/conftest.py +140 -0
- firefighter_tests/test_slack/views/modals/test_close.py +71 -9
- firefighter_tests/test_slack/views/modals/test_closure_reason_modal.py +138 -0
- firefighter_tests/test_slack/views/modals/test_form_utils_multiple_choice.py +249 -0
- firefighter_tests/test_slack/views/modals/test_open.py +146 -2
- firefighter_tests/test_slack/views/modals/test_opening_unified.py +421 -0
- firefighter_tests/test_slack/views/modals/test_update_status.py +331 -7
- firefighter_tests/test_slack/views/modals/test_utils.py +135 -0
- firefighter/raid/views/open_normal.py +0 -139
- firefighter/slack/views/modals/opening/details/critical.py +0 -88
- firefighter_fixtures/raid/area.json +0 -1
- {firefighter_incident-0.0.13.dist-info → firefighter_incident-0.0.15.dist-info}/WHEEL +0 -0
- {firefighter_incident-0.0.13.dist-info → firefighter_incident-0.0.15.dist-info}/entry_points.txt +0 -0
- {firefighter_incident-0.0.13.dist-info → firefighter_incident-0.0.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -40,18 +40,18 @@ logger = logging.getLogger(__name__)
|
|
|
40
40
|
TZ = timezone.get_current_timezone()
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
class
|
|
44
|
-
model: type[
|
|
43
|
+
class IncidentCategoryManager(models.Manager["IncidentCategory"]):
|
|
44
|
+
model: type[IncidentCategory]
|
|
45
45
|
|
|
46
46
|
def queryset_with_mtbf(
|
|
47
47
|
self,
|
|
48
48
|
date_from: datetime,
|
|
49
49
|
date_to: datetime,
|
|
50
|
-
queryset: QuerySet[
|
|
50
|
+
queryset: QuerySet[IncidentCategory] | None = None,
|
|
51
51
|
metric_type: str = "time_to_fix",
|
|
52
52
|
field_name: str = "mtbf",
|
|
53
|
-
) -> QuerySet[
|
|
54
|
-
"""Returns a queryset of
|
|
53
|
+
) -> QuerySet[IncidentCategory]:
|
|
54
|
+
"""Returns a queryset of incident categories with an additional `mtbf` field."""
|
|
55
55
|
date_to = min(date_to, datetime.now(tz=TZ))
|
|
56
56
|
|
|
57
57
|
date_interval = date_to - date_from
|
|
@@ -62,12 +62,12 @@ class ComponentManager(models.Manager["Component"]):
|
|
|
62
62
|
.annotate(
|
|
63
63
|
metric_subquery=Subquery(
|
|
64
64
|
IncidentMetric.objects.filter(
|
|
65
|
-
|
|
65
|
+
incident__incident_category=OuterRef("pk"),
|
|
66
66
|
metric_type__type=metric_type,
|
|
67
67
|
incident__created_at__gte=date_from,
|
|
68
68
|
incident__created_at__lte=date_to,
|
|
69
69
|
)
|
|
70
|
-
.values("
|
|
70
|
+
.values("incident__incident_category")
|
|
71
71
|
.annotate(sum_downtime=Sum("duration"))
|
|
72
72
|
.values("sum_downtime")
|
|
73
73
|
)
|
|
@@ -95,11 +95,11 @@ class ComponentManager(models.Manager["Component"]):
|
|
|
95
95
|
|
|
96
96
|
@staticmethod
|
|
97
97
|
def search(
|
|
98
|
-
queryset: QuerySet[
|
|
99
|
-
) -> tuple[QuerySet[
|
|
98
|
+
queryset: QuerySet[IncidentCategory] | None, search_term: str
|
|
99
|
+
) -> tuple[QuerySet[IncidentCategory], bool]:
|
|
100
100
|
# XXX Common search method
|
|
101
101
|
if queryset is None:
|
|
102
|
-
queryset =
|
|
102
|
+
queryset = IncidentCategory.objects.all()
|
|
103
103
|
|
|
104
104
|
# If not search, return the original queryset
|
|
105
105
|
if search_term is None or search_term.strip() == "":
|
|
@@ -135,24 +135,24 @@ class ComponentManager(models.Manager["Component"]):
|
|
|
135
135
|
return queryset, False
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
class
|
|
139
|
-
objects:
|
|
138
|
+
class IncidentCategory(models.Model):
|
|
139
|
+
objects: IncidentCategoryManager = IncidentCategoryManager()
|
|
140
140
|
|
|
141
141
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
142
142
|
name = models.CharField(max_length=128)
|
|
143
143
|
description = models.TextField(blank=True)
|
|
144
144
|
order = models.IntegerField(
|
|
145
145
|
default=0,
|
|
146
|
-
help_text="Order of the
|
|
146
|
+
help_text="Order of the incident category in the list. Should be unique per `Group`.",
|
|
147
147
|
)
|
|
148
148
|
group = models.ForeignKey(Group, on_delete=models.PROTECT)
|
|
149
149
|
private = models.BooleanField(
|
|
150
150
|
default=False,
|
|
151
|
-
help_text="If true, incident created with this
|
|
151
|
+
help_text="If true, incident created with this incident category won't be communicated, and conversations will be made private. This is useful for sensitive incident categories. In the future, private incidents may be visible only to its members.",
|
|
152
152
|
)
|
|
153
153
|
deploy_warning = models.BooleanField(
|
|
154
154
|
default=True,
|
|
155
|
-
help_text="If true, a warning will be sent when creating an incident of high severity with this
|
|
155
|
+
help_text="If true, a warning will be sent when creating an incident of high severity with this incident category.",
|
|
156
156
|
)
|
|
157
157
|
|
|
158
158
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
@@ -169,16 +169,17 @@ class Component(models.Model):
|
|
|
169
169
|
|
|
170
170
|
class Meta(TypedModelMeta):
|
|
171
171
|
ordering = ["order"]
|
|
172
|
+
verbose_name_plural = "incident categories"
|
|
172
173
|
|
|
173
174
|
def __str__(self) -> str:
|
|
174
175
|
return f"{'🔒 ' if self.private else ''}{self.name}"
|
|
175
176
|
|
|
176
177
|
def get_absolute_url(self) -> str:
|
|
177
|
-
return reverse("incidents:
|
|
178
|
+
return reverse("incidents:incident-category-detail", kwargs={"incident_category_id": self.id})
|
|
178
179
|
|
|
179
180
|
|
|
180
|
-
class
|
|
181
|
-
"""Set of filters for
|
|
181
|
+
class IncidentCategoryFilterSet(django_filters.FilterSet):
|
|
182
|
+
"""Set of filters for IncidentCategory, share by Web UI and API."""
|
|
182
183
|
|
|
183
184
|
id = django_filters.CharFilter(lookup_expr="iexact")
|
|
184
185
|
private = django_filters.BooleanFilter()
|
|
@@ -194,30 +195,30 @@ class ComponentFilterSet(django_filters.FilterSet):
|
|
|
194
195
|
label="MTBF period",
|
|
195
196
|
)
|
|
196
197
|
search = django_filters.CharFilter(
|
|
197
|
-
field_name="search", method="
|
|
198
|
+
field_name="search", method="incident_category_search", label="Search"
|
|
198
199
|
)
|
|
199
200
|
|
|
200
201
|
@staticmethod
|
|
201
|
-
def
|
|
202
|
-
queryset: QuerySet[
|
|
203
|
-
) -> QuerySet[
|
|
204
|
-
"""Search
|
|
202
|
+
def incident_category_search(
|
|
203
|
+
queryset: QuerySet[IncidentCategory], _name: str, value: str
|
|
204
|
+
) -> QuerySet[IncidentCategory]:
|
|
205
|
+
"""Search incident categories by title, description, and ID.
|
|
205
206
|
|
|
206
207
|
Args:
|
|
207
|
-
queryset (QuerySet[
|
|
208
|
+
queryset (QuerySet[IncidentCategory]): Queryset to search in.
|
|
208
209
|
_name:
|
|
209
210
|
value (str): Value to search for.
|
|
210
211
|
|
|
211
212
|
Returns:
|
|
212
|
-
QuerySet[
|
|
213
|
+
QuerySet[IncidentCategory]: Search results.
|
|
213
214
|
"""
|
|
214
|
-
return
|
|
215
|
+
return IncidentCategory.objects.search(queryset=queryset, search_term=value)[0]
|
|
215
216
|
|
|
216
217
|
@staticmethod
|
|
217
218
|
def metrics_period_filter(
|
|
218
|
-
queryset: QuerySet[
|
|
219
|
+
queryset: QuerySet[IncidentCategory],
|
|
219
220
|
_name: str,
|
|
220
221
|
value: tuple[datetime, datetime, Any, Any],
|
|
221
|
-
) -> QuerySet[
|
|
222
|
+
) -> QuerySet[IncidentCategory]:
|
|
222
223
|
gte, lte, _, _ = value
|
|
223
|
-
return
|
|
224
|
+
return IncidentCategory.objects.queryset_with_mtbf(gte, lte, queryset=queryset)
|
|
@@ -11,8 +11,8 @@ from django.utils import timezone
|
|
|
11
11
|
from django_stubs_ext.db.models import TypedModelMeta
|
|
12
12
|
|
|
13
13
|
from firefighter.incidents.enums import IncidentStatus
|
|
14
|
-
from firefighter.incidents.models.component import Component
|
|
15
14
|
from firefighter.incidents.models.environment import Environment
|
|
15
|
+
from firefighter.incidents.models.incident_category import IncidentCategory
|
|
16
16
|
from firefighter.incidents.models.priority import Priority
|
|
17
17
|
from firefighter.incidents.models.severity import Severity
|
|
18
18
|
from firefighter.incidents.models.user import User
|
|
@@ -75,8 +75,8 @@ class IncidentUpdate(models.Model):
|
|
|
75
75
|
incident = models.ForeignKey(
|
|
76
76
|
"Incident", on_delete=models.CASCADE
|
|
77
77
|
)
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
incident_category = models.ForeignKey(
|
|
79
|
+
IncidentCategory, null=True, blank=True, on_delete=models.SET_NULL
|
|
80
80
|
)
|
|
81
81
|
created_by = models.ForeignKey(
|
|
82
82
|
User, null=True, blank=True, on_delete=models.SET_NULL
|