From aa934aee67df62596c6a66055e061e3531b4a30c Mon Sep 17 00:00:00 2001 From: arad carmi Date: Thu, 13 Jun 2024 18:40:50 +0300 Subject: [PATCH 01/10] added the new validation --- ...PB103_is_playbook_has_unconnected_tasks.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py diff --git a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py new file mode 100644 index 00000000000..1e74b0e64f8 --- /dev/null +++ b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +from typing import Iterable, List + +from demisto_sdk.commands.content_graph.objects.playbook import Playbook +from demisto_sdk.commands.validate.validators.base_validator import ( + BaseValidator, + ValidationResult, +) + +ContentTypes = Playbook + + +class IsPlaybookHasUnconnectedTasks(BaseValidator[ContentTypes]): + error_code = "PB103" + description = "Checks whether there is an unconnected task." + rationale = "Checks whether there is an unconnected task to the root task." + error_message = ( + "Playbook conditional task with id:{task_id} has task with unreachable " + 'next task condition "{next_task_branch}". Please remove this task or add ' + "this condition to condition task with id:{task_id}." + ) + related_field = "tasks" + is_auto_fixable = False + + @staticmethod + def _is_unconnected_task(playbook: ContentTypes) -> bool: + """Checks whether a playbook has an unconnected task. + Args: + - playbook (ContentTypes): The playbook to check. + Return: + - bool. True if the playbook has an unconnected task, False otherwise. + """ + start_task_id = playbook.data.get("starttaskid") + tasks = playbook.tasks + tasks_bucket = set() + next_tasks_bucket = set() + + for task_id, task in tasks.items(): + if task_id != start_task_id: + tasks_bucket.add(task_id) + next_tasks = task.get("nexttasks", {}) + for next_task_ids in next_tasks.values(): + if next_task_ids: + next_tasks_bucket.update(next_task_ids) + orphan_tasks = tasks_bucket.difference(next_tasks_bucket) + if orphan_tasks: + return False + return tasks_bucket.issubset(next_tasks_bucket) + + def is_valid(self, content_items: Iterable[ContentTypes]) -> List[ValidationResult]: + return [ + ValidationResult( + validator=self, + message=self.error_message, + content_object=content_item, + ) + for content_item in content_items + if (self._is_unconnected_task(content_item)) + ] From f631c612de9fadedf59d38808fea118507ea34e2 Mon Sep 17 00:00:00 2001 From: arad carmi Date: Thu, 13 Jun 2024 18:41:26 +0300 Subject: [PATCH 02/10] added UT --- .../validate/tests/PB_validators_test.py | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/demisto_sdk/commands/validate/tests/PB_validators_test.py b/demisto_sdk/commands/validate/tests/PB_validators_test.py index 3b689e31d28..4f804db4396 100644 --- a/demisto_sdk/commands/validate/tests/PB_validators_test.py +++ b/demisto_sdk/commands/validate/tests/PB_validators_test.py @@ -7,6 +7,9 @@ from demisto_sdk.commands.validate.validators.PB_validators.PB101_is_playbook_has_unreachable_condition import ( IsAskConditionHasUnreachableConditionValidator, ) +from demisto_sdk.commands.validate.validators.PB_validators.PB103_is_playbook_has_unconnected_tasks import ( + IsPlaybookHasUnconnectedTasks, +) from demisto_sdk.commands.validate.validators.PB_validators.PB104_deprecated_description import ( DeprecatedDescriptionValidator, ) @@ -188,7 +191,6 @@ def test_is_deprecated_with_invalid_description(content_item, expected_result): def test_IsAskConditionHasUnreachableConditionValidator(): - playbook = create_playbook_object() assert not IsAskConditionHasUnreachableConditionValidator().is_valid([playbook]) playbook.tasks = { @@ -203,7 +205,6 @@ def test_IsAskConditionHasUnreachableConditionValidator(): def test_IsAskConditionHasUnhandledReplyOptionsValidator(): - playbook = create_playbook_object() assert not IsAskConditionHasUnhandledReplyOptionsValidator().is_valid([playbook]) playbook.tasks = { @@ -215,3 +216,57 @@ def test_IsAskConditionHasUnhandledReplyOptionsValidator(): } } assert IsAskConditionHasUnhandledReplyOptionsValidator().is_valid([playbook]) + + +def test_is_playbook_has_unconnected_tasks(): + """ + Given: A playbook with tasks that are connected to each other. + When: Validating the playbook. + Then: The playbook is valid. + """ + playbook = create_playbook_object(paths=["starttaskid"], values=["0"]) + playbook.tasks = { + "0": { + "id": "test task", + "type": "regular", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"#none#": "1"}, + }, + "1": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + }, + } + assert IsPlaybookHasUnconnectedTasks().is_valid([playbook]) + + +def test_is_playbook_has_unconnected_tasks_not_valid(): + """ + Given: A playbook with tasks that are not connected to the root task. + When: Validating the playbook. + Then: The playbook is not valid. + """ + playbook = create_playbook_object(paths=["starttaskid"], values=["0"]) + playbook.tasks = { + "0": { + "id": "test task", + "type": "regular", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"#none#": "1"}, + }, + "1": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + }, + "3": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + }, + } + assert not IsPlaybookHasUnconnectedTasks().is_valid([playbook]) From 09626cb230ec207e11ee5bf5dc567013af73aa45 Mon Sep 17 00:00:00 2001 From: arad carmi Date: Thu, 13 Jun 2024 18:42:10 +0300 Subject: [PATCH 03/10] added the validation to the config file --- demisto_sdk/commands/validate/sdk_validation_config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demisto_sdk/commands/validate/sdk_validation_config.toml b/demisto_sdk/commands/validate/sdk_validation_config.toml index bb7caad0734..805a7355d66 100644 --- a/demisto_sdk/commands/validate/sdk_validation_config.toml +++ b/demisto_sdk/commands/validate/sdk_validation_config.toml @@ -29,7 +29,7 @@ select = [ "IN100", "IN101", "IN102", "IN104", "IN106", "IN107", "IN108", "IN109", "IN110", "IN112", "IN113", "IN114", "IN115", "IN117", "IN118", "IN121", "IN122", "IN123", "IN124", "IN125", "IN126", "IN127", "IN130", "IN131", "IN134", "IN135", "IN139", "IN141", "IN142", "IN144", "IN145", "IN146", "IN149", "IN150", "IN151", "IN152", "IN153", "IN154", "IN156", "IN158", "IN159", "IN160", "IN161", "IN162", - "PB100", "PB101","PB104","PB118", "PB123", + "PB100", "PB101","PB103","PB104","PB118", "PB123", "DO100", "DO101", "DO102", "DO103", "DO104", "DO105", "DO106", "DS100", "DS107", "SC100", "SC105", "SC106", "SC109", From 91a224cd16bfb72800264f00d9b02e8ccac8b29c Mon Sep 17 00:00:00 2001 From: arad carmi Date: Thu, 13 Jun 2024 18:45:00 +0300 Subject: [PATCH 04/10] added changelog --- .changelog/4340.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changelog/4340.yml diff --git a/.changelog/4340.yml b/.changelog/4340.yml new file mode 100644 index 00000000000..944eafd51aa --- /dev/null +++ b/.changelog/4340.yml @@ -0,0 +1,4 @@ +changes: +- description: Added the PB103 to the new validation format. Validates that the modeling rules have a schema file. + type: internal +pr_number: 4340 From 5ab7f1c0677bd26820108b5b52a968a100dcc87e Mon Sep 17 00:00:00 2001 From: arad carmi Date: Thu, 13 Jun 2024 18:48:33 +0300 Subject: [PATCH 05/10] fixed description --- .changelog/4340.yml | 2 +- .../PB_validators/PB103_is_playbook_has_unconnected_tasks.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changelog/4340.yml b/.changelog/4340.yml index 944eafd51aa..3b0c7012a5f 100644 --- a/.changelog/4340.yml +++ b/.changelog/4340.yml @@ -1,4 +1,4 @@ changes: -- description: Added the PB103 to the new validation format. Validates that the modeling rules have a schema file. +- description: Added the PB103 to the new validation format. Validate whether there is an unconnected task. type: internal pr_number: 4340 diff --git a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py index 1e74b0e64f8..c06e97af738 100644 --- a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py +++ b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py @@ -13,8 +13,8 @@ class IsPlaybookHasUnconnectedTasks(BaseValidator[ContentTypes]): error_code = "PB103" - description = "Checks whether there is an unconnected task." - rationale = "Checks whether there is an unconnected task to the root task." + description = "Validate whether there is an unconnected task." + rationale = "Validate whether there is an unconnected task to the root task." error_message = ( "Playbook conditional task with id:{task_id} has task with unreachable " 'next task condition "{next_task_branch}". Please remove this task or add ' From bc6ba21409a1902bc8ab47dc142ef7580b51fa5e Mon Sep 17 00:00:00 2001 From: arad carmi Date: Sun, 16 Jun 2024 13:59:32 +0300 Subject: [PATCH 06/10] fixed cr notes --- .../validate/sdk_validation_config.toml | 2 +- .../validate/tests/PB_validators_test.py | 15 +++++++++++-- ...PB103_is_playbook_has_unconnected_tasks.py | 21 +++++++------------ 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/demisto_sdk/commands/validate/sdk_validation_config.toml b/demisto_sdk/commands/validate/sdk_validation_config.toml index 733d8bccf13..95996ad2a6d 100644 --- a/demisto_sdk/commands/validate/sdk_validation_config.toml +++ b/demisto_sdk/commands/validate/sdk_validation_config.toml @@ -52,7 +52,7 @@ select = [ "IN131", "IN134", "IN135", "IN139", "IN141", "IN142", "IN144", "IN145", "IN146", "IN149", "IN150", "IN151", "IN152", "IN153", "IN154", "IN156", "IN158", "IN159", "IN160", "IN161", "IN162", "LO107", - "PB100", "PB101","PB104", "PB123", + "PB100", "PB101","PB103","PB104", "PB123", "BA100", "BA101", "BA105", "BA106", "BA110", "BA111", "BA113", "BA116", "BA118", "BA119", "BA126", "DS100", "PA100", "PA101", "PA102", "PA103", "PA104", "PA105", "PA107", "PA108", "PA109", "PA111", "PA113", "PA115", "PA117", "PA118", "PA119", "PA120", diff --git a/demisto_sdk/commands/validate/tests/PB_validators_test.py b/demisto_sdk/commands/validate/tests/PB_validators_test.py index 4f804db4396..771ae98f011 100644 --- a/demisto_sdk/commands/validate/tests/PB_validators_test.py +++ b/demisto_sdk/commands/validate/tests/PB_validators_test.py @@ -8,6 +8,7 @@ IsAskConditionHasUnreachableConditionValidator, ) from demisto_sdk.commands.validate.validators.PB_validators.PB103_is_playbook_has_unconnected_tasks import ( + ERROR_MSG, IsPlaybookHasUnconnectedTasks, ) from demisto_sdk.commands.validate.validators.PB_validators.PB104_deprecated_description import ( @@ -239,7 +240,8 @@ def test_is_playbook_has_unconnected_tasks(): "nexttasks": {"no": ["2"]}, }, } - assert IsPlaybookHasUnconnectedTasks().is_valid([playbook]) + validation_results = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) + assert len(validation_results) == 0 # No validation results should be returned def test_is_playbook_has_unconnected_tasks_not_valid(): @@ -268,5 +270,14 @@ def test_is_playbook_has_unconnected_tasks_not_valid(): "message": {"replyOptions": ["yes"]}, "nexttasks": {"no": ["2"]}, }, + "4": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + }, } - assert not IsPlaybookHasUnconnectedTasks().is_valid([playbook]) + orphan_tasks = ["3", "4"] + validation_result = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) + assert validation_result + assert validation_result[0].message == ERROR_MSG.format(orphan_tasks=orphan_tasks) diff --git a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py index c06e97af738..b1046a9d6f1 100644 --- a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py +++ b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Iterable, List +from typing import Any, Iterable, List from demisto_sdk.commands.content_graph.objects.playbook import Playbook from demisto_sdk.commands.validate.validators.base_validator import ( @@ -9,22 +9,19 @@ ) ContentTypes = Playbook +ERROR_MSG = "The following tasks ids have no previous tasks: {orphan_tasks}" class IsPlaybookHasUnconnectedTasks(BaseValidator[ContentTypes]): error_code = "PB103" description = "Validate whether there is an unconnected task." - rationale = "Validate whether there is an unconnected task to the root task." - error_message = ( - "Playbook conditional task with id:{task_id} has task with unreachable " - 'next task condition "{next_task_branch}". Please remove this task or add ' - "this condition to condition task with id:{task_id}." - ) + rationale = "Make sure there are no unconnected tasks to ensure the playbook will work as expected." + error_message = ERROR_MSG related_field = "tasks" is_auto_fixable = False @staticmethod - def _is_unconnected_task(playbook: ContentTypes) -> bool: + def is_unconnected_task(playbook: ContentTypes) -> set[Any]: """Checks whether a playbook has an unconnected task. Args: - playbook (ContentTypes): The playbook to check. @@ -44,17 +41,15 @@ def _is_unconnected_task(playbook: ContentTypes) -> bool: if next_task_ids: next_tasks_bucket.update(next_task_ids) orphan_tasks = tasks_bucket.difference(next_tasks_bucket) - if orphan_tasks: - return False - return tasks_bucket.issubset(next_tasks_bucket) + return orphan_tasks def is_valid(self, content_items: Iterable[ContentTypes]) -> List[ValidationResult]: return [ ValidationResult( validator=self, - message=self.error_message, + message=self.error_message.format(orphan_tasks=sorted(orphan_tasks)), content_object=content_item, ) for content_item in content_items - if (self._is_unconnected_task(content_item)) + if (orphan_tasks := self.is_unconnected_task(content_item)) ] From cb3117cab420d86e69c173e8cc1db423d2ee8631 Mon Sep 17 00:00:00 2001 From: arad carmi Date: Mon, 17 Jun 2024 11:09:56 +0300 Subject: [PATCH 07/10] changed to task field --- .../validate/tests/PB_validators_test.py | 96 ++++++++++++------- ...PB103_is_playbook_has_unconnected_tasks.py | 8 +- 2 files changed, 64 insertions(+), 40 deletions(-) diff --git a/demisto_sdk/commands/validate/tests/PB_validators_test.py b/demisto_sdk/commands/validate/tests/PB_validators_test.py index fc9c575a416..b33de5183ae 100644 --- a/demisto_sdk/commands/validate/tests/PB_validators_test.py +++ b/demisto_sdk/commands/validate/tests/PB_validators_test.py @@ -234,18 +234,26 @@ def test_is_playbook_has_unconnected_tasks(): """ playbook = create_playbook_object(paths=["starttaskid"], values=["0"]) playbook.tasks = { - "0": { - "id": "test task", - "type": "regular", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"#none#": "1"}, - }, - "1": { - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - }, + "0": TaskConfig( + **{ + "id": "test task", + "type": "regular", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"#none#": ["1"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a631", + } + ), + "1": TaskConfig( + **{ + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + } + ), } validation_results = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) assert len(validation_results) == 0 # No validation results should be returned @@ -259,30 +267,46 @@ def test_is_playbook_has_unconnected_tasks_not_valid(): """ playbook = create_playbook_object(paths=["starttaskid"], values=["0"]) playbook.tasks = { - "0": { - "id": "test task", - "type": "regular", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"#none#": "1"}, - }, - "1": { - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - }, - "3": { - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - }, - "4": { - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - }, + "0": TaskConfig( + **{ + "id": "test task", + "type": "regular", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"#none#": ["1"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a631", + } + ), + "1": TaskConfig( + **{ + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + } + ), + "3": TaskConfig( + **{ + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + } + ), + "4": TaskConfig( + **{ + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + } + ), } orphan_tasks = ["3", "4"] validation_result = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) diff --git a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py index b1046a9d6f1..5613c7f5051 100644 --- a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py +++ b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py @@ -36,10 +36,10 @@ def is_unconnected_task(playbook: ContentTypes) -> set[Any]: for task_id, task in tasks.items(): if task_id != start_task_id: tasks_bucket.add(task_id) - next_tasks = task.get("nexttasks", {}) - for next_task_ids in next_tasks.values(): - if next_task_ids: - next_tasks_bucket.update(next_task_ids) + if next_tasks := task.nexttasks: + for next_task_ids in next_tasks.values(): + if next_task_ids: + next_tasks_bucket.update(next_task_ids) orphan_tasks = tasks_bucket.difference(next_tasks_bucket) return orphan_tasks From 6b07bf054f5b07513e987dfc2146fdf99c20a901 Mon Sep 17 00:00:00 2001 From: arad carmi Date: Mon, 17 Jun 2024 12:08:45 +0300 Subject: [PATCH 08/10] update CR notes --- .../validate/tests/PB_validators_test.py | 130 +++++++++--------- ...PB103_is_playbook_has_unconnected_tasks.py | 2 +- 2 files changed, 65 insertions(+), 67 deletions(-) diff --git a/demisto_sdk/commands/validate/tests/PB_validators_test.py b/demisto_sdk/commands/validate/tests/PB_validators_test.py index b33de5183ae..7edc45e0be3 100644 --- a/demisto_sdk/commands/validate/tests/PB_validators_test.py +++ b/demisto_sdk/commands/validate/tests/PB_validators_test.py @@ -232,29 +232,30 @@ def test_is_playbook_has_unconnected_tasks(): When: Validating the playbook. Then: The playbook is valid. """ - playbook = create_playbook_object(paths=["starttaskid"], values=["0"]) - playbook.tasks = { - "0": TaskConfig( - **{ - "id": "test task", - "type": "regular", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"#none#": ["1"]}, - "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, - "taskid": "27b9c747-b883-4878-8b60-7f352098a631", - } - ), - "1": TaskConfig( - **{ - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, - "taskid": "27b9c747-b883-4878-8b60-7f352098a632", - } - ), - } + playbook = create_playbook_object( + paths=["starttaskid", "tasks"], + values=[ + "0", + { + "0": { + "id": "test task", + "type": "regular", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"#none#": ["1"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a631", + }, + "1": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + }, + }, + ], + ) validation_results = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) assert len(validation_results) == 0 # No validation results should be returned @@ -265,49 +266,46 @@ def test_is_playbook_has_unconnected_tasks_not_valid(): When: Validating the playbook. Then: The playbook is not valid. """ - playbook = create_playbook_object(paths=["starttaskid"], values=["0"]) - playbook.tasks = { - "0": TaskConfig( - **{ - "id": "test task", - "type": "regular", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"#none#": ["1"]}, - "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, - "taskid": "27b9c747-b883-4878-8b60-7f352098a631", - } - ), - "1": TaskConfig( - **{ - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, - "taskid": "27b9c747-b883-4878-8b60-7f352098a632", - } - ), - "3": TaskConfig( - **{ - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, - "taskid": "27b9c747-b883-4878-8b60-7f352098a632", - } - ), - "4": TaskConfig( - **{ - "id": "test task", - "type": "condition", - "message": {"replyOptions": ["yes"]}, - "nexttasks": {"no": ["2"]}, - "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, - "taskid": "27b9c747-b883-4878-8b60-7f352098a632", - } - ), - } + playbook = create_playbook_object( + paths=["starttaskid", "tasks"], + values=[ + "0", + { + "0": { + "id": "test task", + "type": "regular", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"#none#": ["1"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a631", + }, + "1": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + }, + "3": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + }, + "4": { + "id": "test task", + "type": "condition", + "message": {"replyOptions": ["yes"]}, + "nexttasks": {"no": ["2"]}, + "task": {"id": "27b9c747-b883-4878-8b60-7f352098a63c"}, + "taskid": "27b9c747-b883-4878-8b60-7f352098a632", + }, + }, + ], + ) orphan_tasks = ["3", "4"] validation_result = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) assert validation_result diff --git a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py index 5613c7f5051..acb25bdb581 100644 --- a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py +++ b/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py @@ -9,7 +9,7 @@ ) ContentTypes = Playbook -ERROR_MSG = "The following tasks ids have no previous tasks: {orphan_tasks}" +ERROR_MSG = "The following tasks ids have no previous tasks: {orphan_tasks}." class IsPlaybookHasUnconnectedTasks(BaseValidator[ContentTypes]): From c2e394864c59497b5d43b2d920e9a71969456f98 Mon Sep 17 00:00:00 2001 From: arad carmi Date: Mon, 17 Jun 2024 17:01:27 +0300 Subject: [PATCH 09/10] update CR notes --- .../commands/validate/tests/PB_validators_test.py | 12 ++++++------ ...=> PB103_does_playbook_have_unconnected_tasks.py} | 0 2 files changed, 6 insertions(+), 6 deletions(-) rename demisto_sdk/commands/validate/validators/PB_validators/{PB103_is_playbook_has_unconnected_tasks.py => PB103_does_playbook_have_unconnected_tasks.py} (100%) diff --git a/demisto_sdk/commands/validate/tests/PB_validators_test.py b/demisto_sdk/commands/validate/tests/PB_validators_test.py index 7edc45e0be3..b4adbd80bbb 100644 --- a/demisto_sdk/commands/validate/tests/PB_validators_test.py +++ b/demisto_sdk/commands/validate/tests/PB_validators_test.py @@ -8,9 +8,9 @@ from demisto_sdk.commands.validate.validators.PB_validators.PB101_is_playbook_has_unreachable_condition import ( IsAskConditionHasUnreachableConditionValidator, ) -from demisto_sdk.commands.validate.validators.PB_validators.PB103_is_playbook_has_unconnected_tasks import ( +from demisto_sdk.commands.validate.validators.PB_validators.PB103_does_playbook_have_unconnected_tasks import ( ERROR_MSG, - IsPlaybookHasUnconnectedTasks, + DoesPlaybookHaveUnconnectedTasks, ) from demisto_sdk.commands.validate.validators.PB_validators.PB104_deprecated_description import ( DeprecatedDescriptionValidator, @@ -226,7 +226,7 @@ def test_IsAskConditionHasUnhandledReplyOptionsValidator(): assert IsAskConditionHasUnhandledReplyOptionsValidator().is_valid([playbook]) -def test_is_playbook_has_unconnected_tasks(): +def test_does_playbook_have_unconnected_tasks(): """ Given: A playbook with tasks that are connected to each other. When: Validating the playbook. @@ -256,11 +256,11 @@ def test_is_playbook_has_unconnected_tasks(): }, ], ) - validation_results = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) + validation_results = DoesPlaybookHaveUnconnectedTasks().is_valid([playbook]) assert len(validation_results) == 0 # No validation results should be returned -def test_is_playbook_has_unconnected_tasks_not_valid(): +def test_does_playbook_have_unconnected_tasks_not_valid(): """ Given: A playbook with tasks that are not connected to the root task. When: Validating the playbook. @@ -307,6 +307,6 @@ def test_is_playbook_has_unconnected_tasks_not_valid(): ], ) orphan_tasks = ["3", "4"] - validation_result = IsPlaybookHasUnconnectedTasks().is_valid([playbook]) + validation_result = DoesPlaybookHaveUnconnectedTasks().is_valid([playbook]) assert validation_result assert validation_result[0].message == ERROR_MSG.format(orphan_tasks=orphan_tasks) diff --git a/demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py b/demisto_sdk/commands/validate/validators/PB_validators/PB103_does_playbook_have_unconnected_tasks.py similarity index 100% rename from demisto_sdk/commands/validate/validators/PB_validators/PB103_is_playbook_has_unconnected_tasks.py rename to demisto_sdk/commands/validate/validators/PB_validators/PB103_does_playbook_have_unconnected_tasks.py From 5bb5fb5f4bf1db10d4f8c1fd367aa40665b4bf01 Mon Sep 17 00:00:00 2001 From: arad carmi Date: Mon, 17 Jun 2024 17:02:05 +0300 Subject: [PATCH 10/10] update CR notes --- .../PB_validators/PB103_does_playbook_have_unconnected_tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demisto_sdk/commands/validate/validators/PB_validators/PB103_does_playbook_have_unconnected_tasks.py b/demisto_sdk/commands/validate/validators/PB_validators/PB103_does_playbook_have_unconnected_tasks.py index acb25bdb581..3cce3044792 100644 --- a/demisto_sdk/commands/validate/validators/PB_validators/PB103_does_playbook_have_unconnected_tasks.py +++ b/demisto_sdk/commands/validate/validators/PB_validators/PB103_does_playbook_have_unconnected_tasks.py @@ -12,7 +12,7 @@ ERROR_MSG = "The following tasks ids have no previous tasks: {orphan_tasks}." -class IsPlaybookHasUnconnectedTasks(BaseValidator[ContentTypes]): +class DoesPlaybookHaveUnconnectedTasks(BaseValidator[ContentTypes]): error_code = "PB103" description = "Validate whether there is an unconnected task." rationale = "Make sure there are no unconnected tasks to ensure the playbook will work as expected."