diff --git a/.changelog/4722.yml b/.changelog/4722.yml new file mode 100644 index 00000000000..6510072eebb --- /dev/null +++ b/.changelog/4722.yml @@ -0,0 +1,4 @@ +changes: +- description: Added new BA128 validation which ensures script and integration command names don't start with a digit. + type: feature +pr_number: 4722 diff --git a/demisto_sdk/commands/validate/sdk_validation_config.toml b/demisto_sdk/commands/validate/sdk_validation_config.toml index f1c10cba7b2..5e7760bd201 100644 --- a/demisto_sdk/commands/validate/sdk_validation_config.toml +++ b/demisto_sdk/commands/validate/sdk_validation_config.toml @@ -160,6 +160,7 @@ select = [ "BA118", "BA119", "BA126", + "BA128", "DS100", "DS101", "DS105", @@ -306,6 +307,7 @@ select = [ "BA125", "BA126", "BA127", + "BA128", "PA100", "PA101", "PA102", diff --git a/demisto_sdk/commands/validate/tests/BA_validators_test.py b/demisto_sdk/commands/validate/tests/BA_validators_test.py index 8b171d71970..81f86e24776 100644 --- a/demisto_sdk/commands/validate/tests/BA_validators_test.py +++ b/demisto_sdk/commands/validate/tests/BA_validators_test.py @@ -108,6 +108,9 @@ from demisto_sdk.commands.validate.validators.BA_validators.BA127_is_valid_context_path_depth import ( IsValidContextPathDepthValidator, ) +from demisto_sdk.commands.validate.validators.BA_validators.BA128_is_command_or_script_name_starts_with_digit import ( + IsCommandOrScriptNameStartsWithDigitValidator, +) from TestSuite.repo import ChangeCWD VALUE_WITH_TRAILING_SPACE = "field_with_space_should_fail " @@ -2418,3 +2421,84 @@ def test_IsTestsSectionValidValidator_obtain_invalid_content_items(): for result, expected_msg in zip(results, expected_msgs) ] ) + + +def test_is_command_or_script_name_starts_with_digit_invalid(): + """ + Given + - One invalid integration with two commands (one of which starts with a digit character). + When + - Calling the IsCommandOrScriptNameStartsWithDigitValidator obtain_invalid_content_items function. + Then + - Make sure one failure is returned and the error message contains the relevant command name. + """ + content_items = [ + create_integration_object( + paths=["script.commands"], + values=[ + [ + { + "name": "1system-get-users", + "description": "Get users from 1System", + "deprecated": False, + "arguments": [], + "outputs": [], + }, + { + "name": "one-system-get-assets", + "description": "Get cloud assets from 1System", + "deprecated": False, + "arguments": [], + "outputs": [], + }, + ] + ], + pack_info={"support": XSOAR_SUPPORT}, + ), + ] + expected_msg = ( + "The following integration command names start with a digit: 1system-get-users" + ) + results = ( + IsCommandOrScriptNameStartsWithDigitValidator().obtain_invalid_content_items( + content_items + ) + ) + + assert len(results) == 1 + assert results[0].message == expected_msg + + +def test_is_command_or_script_name_starts_with_digit_valid(): + """ + Given + - One valid integration with one command starting with a letter character. + When + - Calling the IsCommandOrScriptNameStartsWithDigitValidator obtain_invalid_content_items function. + Then + - Make sure no failures are returned. + """ + content_items = [ + create_integration_object( + paths=["script.commands"], + values=[ + [ + { + "name": "one-system-get-users", + "description": "Get users from 1System", + "deprecated": False, + "arguments": [], + "outputs": [], + }, + ] + ], + pack_info={"support": XSOAR_SUPPORT}, + ), + ] + results = ( + IsCommandOrScriptNameStartsWithDigitValidator().obtain_invalid_content_items( + content_items + ) + ) + + assert len(results) == 0 diff --git a/demisto_sdk/commands/validate/validators/BA_validators/BA128_is_command_or_script_name_starts_with_digit.py b/demisto_sdk/commands/validate/validators/BA_validators/BA128_is_command_or_script_name_starts_with_digit.py new file mode 100644 index 00000000000..3bf36669969 --- /dev/null +++ b/demisto_sdk/commands/validate/validators/BA_validators/BA128_is_command_or_script_name_starts_with_digit.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from typing import Iterable, List, Union + +from demisto_sdk.commands.content_graph.objects.integration import Integration +from demisto_sdk.commands.content_graph.objects.script import Script +from demisto_sdk.commands.validate.validators.base_validator import ( + BaseValidator, + ValidationResult, +) + +ContentTypes = Union[Integration, Script] + + +class IsCommandOrScriptNameStartsWithDigitValidator(BaseValidator[ContentTypes]): + error_code = "BA128" + description = "Ensure that integration command names and script names cannot start with a digit." + rationale = "Ensure we don't add commands which are not supported by the platform." + error_message = "The following {0} names start with a digit: {1}" + related_field = "name" + is_auto_fixable = False + + def obtain_invalid_content_items( + self, content_items: Iterable[ContentTypes] + ) -> List[ValidationResult]: + validation_results = [] + + for content_item in content_items: + content_type = "" + invalid_command_names = [] + + if isinstance(content_item, Integration): + content_type = "integration command" + invalid_command_names.extend( + [ + command.name + for command in content_item.commands + if command.name and command.name[0].isdigit() + ] + ) + + elif isinstance(content_item, Script) and content_item.name[0].isdigit(): + content_type = "script" + invalid_command_names.append(content_item.name) + + if invalid_command_names: + validation_results.append( + ValidationResult( + validator=self, + message=self.error_message.format( + content_type, + ", ".join(invalid_command_names), + ), + content_object=content_item, + ) + ) + + return validation_results