-
Notifications
You must be signed in to change notification settings - Fork 525
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(signal instance): allow instance to specify oncall service and c…
…onversation target (#5670) * interim * db update * remove comment * pair programming and test suite * unused import * Update src/dispatch/database/revisions/tenant/versions/2024-12-17_dfc8e213a2c4.py Co-authored-by: David Whittaker <[email protected]> Signed-off-by: Alicia Matsumoto <[email protected]> --------- Signed-off-by: Alicia Matsumoto <[email protected]> Co-authored-by: Alicia Matsumoto <[email protected]> Co-authored-by: David Whittaker <[email protected]>
- Loading branch information
1 parent
c1d8b99
commit 17ac3e2
Showing
5 changed files
with
261 additions
and
21 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
src/dispatch/database/revisions/tenant/versions/2024-12-17_dfc8e213a2c4.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
"""Adds conversation target and oncall service override options to signal instances | ||
Revision ID: dfc8e213a2c4 | ||
Revises: 2d9e4d392ea4 | ||
Create Date: 2024-12-17 10:02:26.920568 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = 'dfc8e213a2c4' | ||
down_revision = '2d9e4d392ea4' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.add_column("signal_instance", sa.Column("conversation_target", sa.String(), nullable=True)) | ||
op.add_column("signal_instance", sa.Column("oncall_service_id", sa.Integer(), nullable=True)) | ||
op.create_foreign_key( | ||
"oncall_service_id_fkey", | ||
"signal_instance", | ||
"service", | ||
["oncall_service_id"], | ||
["id"] | ||
) | ||
|
||
|
||
def downgrade(): | ||
op.drop_constraint("oncall_service_id_fkey", "signal_instance", type_="foreignkey") | ||
op.drop_column("signal_instance", "oncall_service_id") | ||
op.drop_column("signal_instance", "conversation_target") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
from unittest import mock | ||
|
||
import pytest | ||
|
||
from dispatch.exceptions import DispatchException | ||
|
@@ -59,3 +61,180 @@ def test_create_signal_instance_not_enabled(session, signal, case_severity, case | |
signal_instance_data=instance_data, | ||
current_user=user, | ||
) | ||
|
||
def test_create_signal_instance_custom_conversation_target(session, signal, case_severity, case_priority, user, case_type): | ||
from dispatch.signal.flows import create_signal_instance | ||
|
||
case_priority.default = True | ||
case_priority.project_id = signal.project_id | ||
|
||
case_severity.default = True | ||
case_severity.project_id = signal.project_id | ||
|
||
instance_data = {"variant": signal.variant, "conversation_target": "instance-conversation-target"} | ||
signal.conversation_target = "signal-conversation-target" | ||
|
||
signal_instance = create_signal_instance( | ||
db_session=session, | ||
project=signal.project, | ||
signal_instance_data=instance_data, | ||
current_user=user, | ||
) | ||
assert signal_instance.conversation_target == 'instance-conversation-target' | ||
|
||
|
||
def test_create_signal_instance_custom_oncall_service(session, signal, case_severity, case_priority, user, services): | ||
from dispatch.signal.flows import create_signal_instance | ||
|
||
case_priority.default = True | ||
case_priority.project_id = signal.project_id | ||
|
||
case_severity.default = True | ||
case_severity.project_id = signal.project_id | ||
|
||
service_0, service_1 = services | ||
service_0.project_id = signal.project_id | ||
service_1.project_id = signal.project_id | ||
|
||
signal.oncall_service = service_0 | ||
instance_data = {"variant": signal.variant, "oncall_service": service_1} | ||
|
||
signal_instance = create_signal_instance( | ||
db_session=session, | ||
project=signal.project, | ||
signal_instance_data=instance_data, | ||
current_user=user, | ||
) | ||
assert signal_instance.oncall_service.id == service_1.id | ||
|
||
def test_signal_instance_create_flow_custom_attributes(session, signal, case_severity, case_priority, user, services, signal_instance, oncall_plugin, case_type, case): | ||
from dispatch.signal.flows import signal_instance_create_flow | ||
from dispatch.service import flows as service_flows | ||
from dispatch.case import service as case_service | ||
|
||
case_priority.default = True | ||
case_priority.project_id = signal.project_id | ||
|
||
case_severity.default = True | ||
case_severity.project_id = signal.project_id | ||
|
||
service_0, service_1 = services | ||
service_0.project_id = signal.project_id | ||
service_1.project_id = signal.project_id | ||
|
||
signal_instance.oncall_service = service_0 | ||
signal_instance.signal.oncall_service = service_1 | ||
signal_instance.conversation_target = "instance-conversation-target" | ||
signal_instance.signal.conversation_target = "signal-conversation-target" | ||
|
||
with mock.patch.object(service_flows, "resolve_oncall") as mock_resolve_oncall, \ | ||
mock.patch.object(case_service, "create") as mock_case_create, \ | ||
mock.patch("dispatch.case.flows.case_new_create_flow") as mock_case_new_create_flow: | ||
mock_resolve_oncall.side_effect = lambda service, db_session: "[email protected]" if service.id == service_0.id else None | ||
mock_case_create.return_value = case | ||
|
||
post_flow_instance = signal_instance_create_flow( | ||
signal_instance_id=signal_instance.id, | ||
db_session=session, | ||
current_user=user | ||
) | ||
case_in_arg = mock_case_create.call_args[1]['case_in'] | ||
assert case_in_arg.assignee.individual.email == "[email protected]" | ||
mock_case_new_create_flow.assert_called_once_with( | ||
db_session=session, | ||
organization_slug=None, | ||
service_id=None, | ||
conversation_target="instance-conversation-target", | ||
case_id=post_flow_instance.case.id, | ||
create_all_resources=False | ||
) | ||
|
||
def test_signal_instance_create_flow_use_signal_attributes(session, signal, case_severity, case_priority, user, services, signal_instance, | ||
case_type, case): | ||
""" | ||
If the signal instance does not specify a conversation target or on-call service, use the signal's configurations | ||
before the case type's configurations. | ||
""" | ||
from dispatch.signal.flows import signal_instance_create_flow | ||
from dispatch.service import flows as service_flows | ||
from dispatch.case import service as case_service | ||
|
||
case_priority.default = True | ||
case_priority.project_id = signal.project_id | ||
|
||
case_severity.default = True | ||
case_severity.project_id = signal.project_id | ||
|
||
service_0, service_1 = services | ||
service_0.project_id = signal.project_id | ||
service_1.project_id = signal.project_id | ||
|
||
signal_instance.signal.oncall_service = service_0 | ||
signal_instance.signal.conversation_target = "signal-conversation-target" | ||
case_type.oncall_service = service_1 | ||
case_type.conversation_target = "case-type-conversation-target" | ||
signal_instance.signal.case_type = case_type | ||
|
||
with mock.patch.object(service_flows, "resolve_oncall") as mock_resolve_oncall, \ | ||
mock.patch.object(case_service, "create") as mock_case_create, \ | ||
mock.patch("dispatch.case.flows.case_new_create_flow") as mock_case_new_create_flow: | ||
|
||
mock_resolve_oncall.side_effect = lambda service, db_session: "[email protected]" if service.id == service_0.id else None | ||
mock_case_create.return_value = case | ||
|
||
post_flow_instance = signal_instance_create_flow( | ||
signal_instance_id=signal_instance.id, | ||
db_session=session, | ||
current_user=user | ||
) | ||
case_in_arg = mock_case_create.call_args[1]['case_in'] | ||
assert case_in_arg.assignee.individual.email == "[email protected]" | ||
mock_case_new_create_flow.assert_called_once_with( | ||
db_session=session, | ||
organization_slug=None, | ||
service_id=None, | ||
conversation_target="signal-conversation-target", | ||
case_id=post_flow_instance.case.id, | ||
create_all_resources=False | ||
) | ||
|
||
|
||
def test_signal_instance_create_flow_use_case_type_attributes(session, signal, case_severity, case_priority, user, service, case, signal_instance, case_type): | ||
""" | ||
If the signal instance and the signal both do not specify conversation targets or on-call services, use the case type's configurations. | ||
""" | ||
from dispatch.signal.flows import signal_instance_create_flow | ||
from dispatch.service import flows as service_flows | ||
from dispatch.case import service as case_service | ||
|
||
case_priority.default = True | ||
case_priority.project_id = signal.project_id | ||
|
||
case_severity.default = True | ||
case_severity.project_id = signal.project_id | ||
|
||
case_type.oncall_service = service | ||
case_type.conversation_target = "case-type-conversation-target" | ||
signal_instance.signal.case_type = case_type | ||
|
||
with mock.patch.object(service_flows, "resolve_oncall") as mock_resolve_oncall, \ | ||
mock.patch.object(case_service, "create") as mock_case_create, \ | ||
mock.patch("dispatch.case.flows.case_new_create_flow") as mock_case_new_create_flow: | ||
mock_resolve_oncall.side_effect = lambda service, db_session: "[email protected]" | ||
mock_case_create.return_value = case | ||
|
||
post_flow_instance = signal_instance_create_flow( | ||
signal_instance_id=signal_instance.id, | ||
db_session=session, | ||
current_user=user | ||
) | ||
case_in_arg = mock_case_create.call_args[1]['case_in'] | ||
assert case_in_arg.assignee.individual.email == "[email protected]" | ||
mock_case_new_create_flow.assert_called_once_with( | ||
db_session=session, | ||
organization_slug=None, | ||
service_id=None, | ||
conversation_target="case-type-conversation-target", | ||
case_id=post_flow_instance.case.id, | ||
create_all_resources=False | ||
) |