diff --git a/.changelog/4373.yml b/.changelog/4373.yml new file mode 100644 index 00000000000..a45c58731be --- /dev/null +++ b/.changelog/4373.yml @@ -0,0 +1,4 @@ +changes: + - description: Added RM107 to the new validation format. The validation checks that all placeholders are removed and all sections are filled in the readme files. + type: internal +pr_number: 4373 diff --git a/demisto_sdk/commands/validate/sdk_validation_config.toml b/demisto_sdk/commands/validate/sdk_validation_config.toml index 5a78e8ad2f3..dd651e2b51c 100644 --- a/demisto_sdk/commands/validate/sdk_validation_config.toml +++ b/demisto_sdk/commands/validate/sdk_validation_config.toml @@ -33,7 +33,7 @@ select = [ "DO100", "DO101", "DO102", "DO103", "DO104", "DO105", "DO106", "DS100", "DS101", "DS105", "DS106", "DS107", "DS108", "SC100", "SC105", "SC106", "SC109", - "RM101", "RM104", "RM105", "RM106", "RM109", "RM113", "RM114", + "RM101", "RM104", "RM105", "RM106", "RM107", "RM109", "RM113", "RM114", "CL100", "GF100", "GF101", "GF102", "IF100", "IF101", "IF102", "IF103", "IF104", "IF105", "IF106", "IF116", @@ -59,7 +59,7 @@ select = [ "PA121", "PA123", "PA125", "PA127", "PA130", "PA131", "PA132", "DO100", "DO101", "DO102", "DO103", "DO104", "SC100", "SC105", "SC106", "SC109", - "RM104", "RM105", "RM113", "RM114", + "RM104", "RM105", "RM107", "RM113", "RM114", "CL100", "GF100", "GF101", "IF100", "IF101", "IF102", "IF103", "IF104", "IF105", "IF106", "IF116", diff --git a/demisto_sdk/commands/validate/tests/RM_validators_test.py b/demisto_sdk/commands/validate/tests/RM_validators_test.py index ff7754452ae..bcabebf04c6 100644 --- a/demisto_sdk/commands/validate/tests/RM_validators_test.py +++ b/demisto_sdk/commands/validate/tests/RM_validators_test.py @@ -21,6 +21,9 @@ from demisto_sdk.commands.validate.validators.RM_validators.RM106_is_contain_demisto_word import ( IsContainDemistoWordValidator, ) +from demisto_sdk.commands.validate.validators.RM_validators.RM107_is_template_sentence_in_readme import ( + IsTemplateInReadmeValidator, +) from demisto_sdk.commands.validate.validators.RM_validators.RM108_is_integration_image_path_valid import ( IntegrationRelativeImagePathValidator, ) @@ -542,3 +545,70 @@ def test_ImagePathOnlyReadMeValidator_is_valid_invalid_case(): result = ReadmeRelativeImagePathValidator().is_valid(content_items) assert result[0].message == expected + + +def test_VerifyTemplateInReadmeValidator_valid_case(repo): + """ + Given + content_items. + - Integration with readme that contains %%FILL HERE%% template substring. + - Script with readme that contains %%FILL HERE%% template substring. + - Playbook with readme that contains %%FILL HERE%% template substring. + - Pack with readme that contains %%FILL HERE%% template substring. + When + - Calling the IsTemplateInReadmeValidator is_valid function. + + Then + - Make sure that the validator return the list of the content items, which has %%FILL HERE%% in the readme file. + """ + content_items = [ + create_integration_object( + readme_content="This checks if we have the sentence %%FILL HERE%% in the README.", + ), + create_script_object( + readme_content="This checks if we have the sentence %%FILL HERE%% in the README.", + ), + create_playbook_object( + readme_content="This checks if we have the sentence %%FILL HERE%% in the README.", + ), + create_pack_object( + readme_text="This checks if we have the sentence %%FILL HERE%% in the README.", + ), + ] + + expected_error_message = "The template '%%FILL HERE%%' exists in the following lines of the README content: 1." + validator_results = IsTemplateInReadmeValidator().is_valid(content_items) + assert validator_results + for validator_result in validator_results: + assert validator_result.message == expected_error_message + + +def test_VerifyTemplateInReadmeValidator_invalid_case(repo): + """ + Given + content_items. + - Integration with readme without %%FILL HERE%% template substring. + - Script with readme without %%FILL HERE%% template substring. + - Playbook with readme without %%FILL HERE%% template substring. + - Pack with readme without %%FILL HERE%% template substring. + When + - Calling the IsTemplateInReadmeValidator is_valid function. + + Then + - Make sure that the validator return empty list. + """ + content_items = [ + create_integration_object( + readme_content="The specific template substring is not in the README.", + ), + create_script_object( + readme_content="The specific template substring is not in the README.", + ), + create_playbook_object( + readme_content="The specific template substring is not in the README.", + ), + create_pack_object( + readme_text="The specific template substring is not in the README.", + ), + ] + assert not IsTemplateInReadmeValidator().is_valid(content_items) diff --git a/demisto_sdk/commands/validate/validators/RM_validators/RM107_is_template_sentence_in_readme.py b/demisto_sdk/commands/validate/validators/RM_validators/RM107_is_template_sentence_in_readme.py new file mode 100644 index 00000000000..0035ea3c944 --- /dev/null +++ b/demisto_sdk/commands/validate/validators/RM_validators/RM107_is_template_sentence_in_readme.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +from typing import Iterable, List, Union + +from demisto_sdk.commands.common.tools import search_substrings_by_line +from demisto_sdk.commands.content_graph.objects.integration import Integration +from demisto_sdk.commands.content_graph.objects.pack import Pack +from demisto_sdk.commands.content_graph.objects.playbook import Playbook +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, Playbook, Pack] + + +class IsTemplateInReadmeValidator(BaseValidator[ContentTypes]): + error_code = "RM107" + description = "Checks if there are the generic sentence '%%FILL HERE%%' in the README content." + rationale = "Ensuring our documentation looks good and professional." + error_message = "The template '%%FILL HERE%%' exists in the following lines of the README content: {0}." + related_field = "readme" + is_auto_fixable = False + + def is_valid(self, content_items: Iterable[ContentTypes]) -> List[ValidationResult]: + """ + Checks if there are the generic sentence '%%FILL HERE%%' in the README content. + + Return: + List of ValidationResult that each element has '%%FILL HERE%%' in the README content. + """ + return [ + ValidationResult( + validator=self, + message=self.error_message.format(", ".join(invalid_lines)), + content_object=content_item, + ) + for content_item in content_items + if ( + invalid_lines := search_substrings_by_line( + phrases_to_search=["%%FILL HERE%%"], + text=content_item.readme.file_content, + ) + ) + ]