def test_is_bump_required(self, pack_current_version, git_current_version, expected_result, mocker): """ Given: - Case 1: Version in origin/master is higher than the current version for the pack - Case 2: Version of origin/master is lower than current version (indicating bump has happened already. - Case 3: Version is the same indicating a bump is necessary. - Case 4: Version was not found so default of 99.99.99 is used. When: - Case 1: Bumping release notes with update-release-notes command. - Case 2: Bumping release notes with update-release-notes command. - Case 3: Bumping release notes with update-release-notes command. - Case 4: Bumping release notes with update-release-notes command. Then: - Case 1: Return True and throw error saying "The master branch is currently ahead of your pack's version. Please pull from master and re-run the command." - Case 2: Return False since bump has already happened. - Case 3: Return True since a bump is necessary. - Case 4: Return True and throw error saying "The master branch is currently ahead of your pack's version. Please pull from master and re-run the command." """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN from subprocess import Popen import json update_rn = UpdateRN(pack_path="Packs/Base", update_type='minor', modified_files_in_pack=set(), added_files=set()) mocker.patch.object(UpdateRN, 'get_pack_metadata', return_value={"currentVersion": pack_current_version}) # mocking the only_docs_changed to test only the is_bump_required mocker.patch.object(UpdateRN, 'only_docs_changed', return_value=False) mocker.patch.object(Popen, 'communicate', return_value=(json.dumps({"currentVersion": git_current_version}), '')) mocker.patch('sys.exit', return_value=None) bump_result = update_rn.is_bump_required() assert bump_result is expected_result
def are_release_notes_complete(self): is_valid = True modified_added_files = itertools.chain.from_iterable( (self.added_files or [], self.modified_files or [])) if modified_added_files: for file in modified_added_files: # renamed files will appear in the modified list as a tuple: (old path, new path) if isinstance(file, tuple): file = file[1] checked_file_pack_name = get_pack_name(file) if find_type(file) in SKIP_RELEASE_NOTES_FOR_TYPES: continue elif checked_file_pack_name and checked_file_pack_name == self.pack_name: # Refer image and description file paths to the corresponding yml files file = UpdateRN.change_image_or_desc_file_path(file) update_rn_util = UpdateRN(pack_path=self.pack_path, modified_files_in_pack=set(), update_type=None, added_files=set(), pack=self.pack_name) file_name, file_type = update_rn_util.get_changed_file_name_and_type( file) if file_name and file_type: if (RN_HEADER_BY_FILE_TYPE[file_type] not in self.latest_release_notes) or \ (file_name not in self.latest_release_notes): entity_name = update_rn_util.get_display_name(file) error_message, error_code = Errors.missing_release_notes_entry( file_type, self.pack_name, entity_name) if self.handle_error(error_message, error_code, self.release_notes_file_path): is_valid = False return is_valid
def test_add_and_modify_files_without_update_docker_image(self, mocker): """ Given - Modified .yml file, but relevant release notes is already exist. When - Updating docker image tag. Then - A new record with the updated docker image is added. """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN import os with open('demisto_sdk/commands/update_release_notes/tests_data/Packs/Test/pack_metadata.json', 'r') as file: pack_data = json.load(file) mocker.patch('demisto_sdk.commands.update_release_notes.update_rn.run_command', return_value='+ type:True') mocker.patch('demisto_sdk.commands.update_release_notes.update_rn.pack_name_to_path', return_value='demisto_sdk/commands/update_release_notes/tests_data/Packs/Test') mocker.patch.object(UpdateRN, 'is_bump_required', return_value=True) mocker.patch.object(UpdateRN, 'get_pack_metadata', return_value=pack_data) mocker.patch.object(UpdateRN, 'get_display_name', return_value='Test') mocker.patch.object(UpdateRN, 'build_rn_template', return_value='##### Test\n') mocker.patch.object(UpdateRN, 'return_release_notes_path', return_value='demisto_sdk/commands' '/update_release_notes/tests_data' '/Packs/release_notes/1_1_0.md') client = UpdateRN(pack_path="Packs/Test", update_type='minor', modified_files_in_pack={ 'Packs/Test/Integrations/Test.yml'}, added_files=set('Packs/Test/some_added_file.py')) client.execute_update() with open('demisto_sdk/commands/update_release_notes/tests_data/Packs/release_notes/1_1_0.md', 'r') as file: RN = file.read() os.remove('demisto_sdk/commands/update_release_notes/tests_data/Packs/release_notes/1_1_0.md') assert 'Upgraded the Docker image to dockerimage:python/test:1243' not in RN
def test_update_docker_image_in_yml(self, mocker): """ Given - Modified .yml file When - Updating docker image tag Then - A new release notes is created. and it has a new record for updating docker image. """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN import os with open('demisto_sdk/commands/update_release_notes/tests_data/Packs/Test/pack_metadata.json', 'r') as file: pack_data = json.load(file) mocker.patch('demisto_sdk.commands.update_release_notes.update_rn.run_command', return_value='+ dockerimage:python/test:1243') mocker.patch('demisto_sdk.commands.update_release_notes.update_rn.pack_name_to_path', return_value='demisto_sdk/commands/update_release_notes/tests_data/Packs/Test') mocker.patch.object(UpdateRN, 'is_bump_required', return_value=False) mocker.patch.object(UpdateRN, 'get_pack_metadata', return_value=pack_data) mocker.patch.object(UpdateRN, 'get_display_name', return_value='Test') mocker.patch.object(UpdateRN, 'build_rn_template', return_value='##### Test') mocker.patch.object(UpdateRN, 'return_release_notes_path', return_value='demisto_sdk/commands/update_release_notes/tests_data/Packs/release_notes' '/1_1_0.md') client = UpdateRN(pack_path="Packs/Test", update_type='minor', modified_files_in_pack={'Packs/Test/Integrations/Test.yml'}, added_files=set()) client.execute_update() with open('demisto_sdk/commands/update_release_notes/tests_data/Packs/release_notes/1_1_0.md', 'r') as file: RN = file.read() os.remove('demisto_sdk/commands/update_release_notes/tests_data/Packs/release_notes/1_1_0.md') assert 'Upgraded the Docker image to dockerimage:python/test:1243' in RN
def are_release_notes_complete(self): is_valid = True modified_added_files = itertools.chain.from_iterable((self.added_files or [], self.modified_files or [])) if modified_added_files: for file in modified_added_files: # renamed files will appear in the modified list as a tuple: (old path, new path) if isinstance(file, tuple): file = file[1] if find_type(file) in self.file_types_that_should_not_appear_in_rn: continue elif self.pack_name + '/' in file: # Refer image and description file paths to the corresponding yml files file = UpdateRN.check_for_release_notes_valid_file_path(file) update_rn_util = UpdateRN(pack_path=self.release_notes_file_path, modified_files_in_pack=set(), update_type=None, added_files=set(), pack=self.pack_name) file_name, file_type = update_rn_util.identify_changed_file_type(file) if file_name and file_type: if (file_type not in self.latest_release_notes) or (file_name not in self.latest_release_notes): entity_name = update_rn_util.get_display_name(file) error_message, error_code = Errors.missing_release_notes_entry(file_type, self.pack_name, entity_name) if self.handle_error(error_message, error_code, self.release_notes_file_path): is_valid = False return is_valid
def test_build_rn_template_integration(self): """ Given: - a dict of changed items When: - we want to produce a release notes template Then: - return a markdown string """ expected_result = "\n#### Integrations\n- __Hello World Integration__\n%%UPDATE_RN%%\n" \ "\n#### Playbooks\n- __Hello World Playbook__\n%%UPDATE_RN%%\n" \ "\n#### Scripts\n- __Hello World Script__\n%%UPDATE_RN%%\n" \ "\n#### IncidentFields\n- __Hello World IncidentField__\n%%UPDATE_RN%%\n" \ "\n#### Classifiers\n- __Hello World Classifier__\n%%UPDATE_RN%%\n" \ "\n#### Layouts\n- __Hello World Layout__\n%%UPDATE_RN%%\n" \ "\n#### IncidentTypes\n- __Hello World Incident Type__\n%%UPDATE_RN%%\n" from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack="HelloWorld", update_type='minor', pack_files={'HelloWorld'}) changed_items = { "Hello World Integration": "Integration", "Hello World Playbook": "Playbook", "Hello World Script": "Script", "Hello World IncidentField": "IncidentFields", "Hello World Classifier": "Classifiers", "N/A": "Integration", "Hello World Layout": "Layouts", "Hello World Incident Type": "IncidentTypes", } release_notes = update_rn.build_rn_template(changed_items) assert expected_result == release_notes
def test_bump_version_number_specific(self): """ Given: - a pack name and specific version When: - bumping the version number in the metadata.json Then: - return the correct bumped version number """ shutil.copy(src=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack/pack_metadata.json'), dst=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack/_pack_metadata.json')) expected_version = '2.0.0' from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack="HelloWorld", update_type=None, specific_version='2.0.0', pack_files={'HelloWorld'}, added_files=set()) update_rn.metadata_path = os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack/pack_metadata.json') version_number, _ = update_rn.bump_version_number( pre_release=False, specific_version='2.0.0') assert version_number == expected_version os.remove( os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack/pack_metadata.json')) shutil.copy(src=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack/_pack_metadata.json'), dst=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack/pack_metadata.json'))
def test_ident_changed_file_type_layouts(self, mocker): """ Given: - a filepath of a changed file When: - determining the type of item changed (e.g. Integration, Script, Layout, etc.) Then: - return tuple where first value is the pack name, and second is the item type """ expected_result = ('VulnDB', 'Layout') from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack="VulnDB", update_type='minor', pack_files={'HelloWorld'}, added_files=set()) filepath = os.path.join(TestRNUpdate.FILES_PATH, 'Layouts/VulnDB/VulnDB.json') mocker.patch.object(UpdateRN, 'find_corresponding_yml', return_value='Integrations/VulnDB/VulnDB.yml') mocker.patch.object(UpdateRN, 'get_display_name', return_value='VulnDB') result = update_rn.identify_changed_file_type(filepath) assert expected_result == result
def test_bump_version_number_major_overflow(self): """ Given: - a pack name and a version before an overflow condition When: - bumping the version number in the metadata.json Then: - return ValueError """ shutil.copy(src=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/pack_metadata.json'), dst=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/_pack_metadata.json')) from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack="HelloWorld", update_type='major', pack_files={'HelloWorld'}, added_files=set()) update_rn.metadata_path = os.path.join( TestRNUpdate.FILES_PATH, 'fake_pack_invalid/pack_metadata.json') self.assertRaises(ValueError, update_rn.bump_version_number) os.remove( os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/pack_metadata.json')) shutil.copy(src=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/_pack_metadata.json'), dst=os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/pack_metadata.json'))
def test_execute_update_invalid(self): """ Given: - A protected pack name When: - running the update command Then: - return an error message and exit. """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/Legacy", update_type='minor', modified_files_in_pack=set(), added_files=set()) update_rn.execute_update()
def update_pack_releasenotes(**kwargs): _pack = kwargs.get('pack') update_type = kwargs.get('update_type') pre_release = kwargs.get('pre_release') is_all = kwargs.get('all') modified, added, old, _packs = FilesValidator( use_git=True).get_modified_and_added_files() packs_existing_rn = set() for pf in added: if 'ReleaseNotes' in pf: pack_with_existing_rn = get_pack_name(pf) packs_existing_rn.add(pack_with_existing_rn) if len(packs_existing_rn): existing_rns = ''.join(f"{p}, " for p in packs_existing_rn) print_warning( f"Found existing release notes for the following packs: {existing_rns.rstrip(', ')}" ) if len(_packs) > 1: pack_list = ''.join(f"{p}, " for p in _packs) if not is_all: if _pack: pass else: print_error( f"Detected changes in the following packs: {pack_list.rstrip(', ')}\n" f"To update release notes in a specific pack, please use the -p parameter " f"along with the pack name.") sys.exit(0) if len(modified) < 1: print_warning('No changes were detected.') sys.exit(0) if is_all and not _pack: packs = list(_packs - packs_existing_rn) packs_list = ''.join(f"{p}, " for p in packs) print_warning( f"Adding release notes to the following packs: {packs_list.rstrip(', ')}" ) for pack in packs: update_pack_rn = UpdateRN(pack=pack, update_type=update_type, pack_files=modified, pre_release=pre_release) update_pack_rn.execute_update() elif is_all and _pack: print_error( "Please remove the --all flag when specifying only one pack.") sys.exit(0) else: if _pack: if _pack in packs_existing_rn: print_error( f"New release notes file already found for {_pack}. " f"Please update manually or delete {pack_name_to_path(_pack)}" ) else: update_pack_rn = UpdateRN(pack=_pack, update_type=update_type, pack_files=modified, pre_release=pre_release) update_pack_rn.execute_update()
def test_bump_version_file_not_found(self): """ Given: - a pack name and a metadata which does not exist When: - bumping the version number in the metadata.json Then: - return ValueError """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='major', modified_files_in_pack={'HelloWorld'}, added_files=set()) update_rn.metadata_path = os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/pack_metadata_.json') self.assertRaises(SystemExit, update_rn.bump_version_number)
def test_bump_version_no_version(self): """ Given: - a pack name and a version before an overflow condition When: - bumping the version number in the metadata.json Then: - return ValueError """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type=None, modified_files_in_pack={'HelloWorld'}, added_files=set()) update_rn.metadata_path = os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/pack_metadata.json') self.assertRaises(ValueError, update_rn.bump_version_number)
def test_update_existing_rn(self): """ Given: - Existing release notes and set of changed files When: - rerunning the update command Then: - return updated release notes while preserving the integrity of the existing notes. """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) new_rn = update_rn.update_existing_rn(self.CURRENT_RN, self.CHANGED_FILES) assert self.EXPECTED_RN_RES == new_rn
def test_check_rn_directory(self): """ Given: - a filepath for a release notes directory When: - determining if the directory exists Then: - create the directory if it does not exist """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN filepath = os.path.join(TestRNUpdate.FILES_PATH, 'ReleaseNotes') update_rn = UpdateRN(pack="VulnDB", update_type='minor', pack_files={'HelloWorld'}) update_rn.check_rn_dir(filepath)
def test_create_markdown(self): """ Given: - a filepath for a release notes file and a markdown string When: - creating a new markdown file Then: - create the file or skip if it exists. """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/VulnDB", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) filepath = os.path.join(TestRNUpdate.FILES_PATH, 'ReleaseNotes/1_1_1.md') md_string = '### Test' update_rn.create_markdown(release_notes_path=filepath, rn_string=md_string, changed_files={})
def test_does_pack_metadata_exist_no(self): """ Given: - Checking for the existance of a pack metadata file When: - metadata path is invalid Then: - return False to indicate it does not exist. """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack=set(), added_files=set()) update_rn.metadata_path = 'This/Doesnt/Exist' result = update_rn._does_pack_metadata_exist() assert result is False
def test_build_rn_template_integration(self): """ Given: - a dict of changed items When: - we want to produce a release notes template Then: - return a markdown string """ expected_result = \ "\n#### Classifiers\n##### Hello World Classifier\n- %%UPDATE_RN%%\n" \ "\n#### Connections\n- **Hello World Connection**\n" \ "\n#### Dashboards\n##### Hello World Dashboard\n- %%UPDATE_RN%%\n" \ "\n#### Incident Fields\n- **Hello World IncidentField**\n" \ "\n#### Incident Types\n- **Hello World Incident Type**\n" \ "\n#### Indicator Fields\n- **Hello World Indicator Field**\n" \ "\n#### Indicator Types\n- **Hello World Indicator Type**\n" \ "\n#### Integrations\n##### Hello World Integration\n- %%UPDATE_RN%%\n" \ "\n#### Layouts\n- **Hello World Layout**\n" \ "- **Second Hello World Layout**\n" \ "\n#### Playbooks\n##### Hello World Playbook\n- %%UPDATE_RN%%\n" \ "\n#### Reports\n##### Hello World Report\n- %%UPDATE_RN%%\n" \ "\n#### Scripts\n##### Hello World Script\n- %%UPDATE_RN%%\n" \ "\n#### Widgets\n##### Hello World Widget\n- %%UPDATE_RN%%\n" from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) changed_items = { "Hello World Integration": {"type": "Integration", "description": "", "is_new_file": False}, "Hello World Playbook": {"type": "Playbook", "description": "", "is_new_file": False}, "Hello World Script": {"type": "Script", "description": "", "is_new_file": False}, "Hello World IncidentField": {"type": "Incident Fields", "description": "", "is_new_file": False}, "Hello World Classifier": {"type": "Classifiers", "description": "", "is_new_file": False}, "N/A": {"type": "Integration", "description": "", "is_new_file": False}, "Hello World Layout": {"type": "Layouts", "description": "", "is_new_file": False}, "Hello World Incident Type": {"type": "Incident Types", "description": "", "is_new_file": False}, "Hello World Indicator Type": {"type": "Indicator Types", "description": "", "is_new_file": False}, "Hello World Indicator Field": {"type": "Indicator Fields", "description": "", "is_new_file": False}, "Second Hello World Layout": {"type": "Layouts", "description": "", "is_new_file": False}, "Hello World Widget": {"type": "Widgets", "description": "", "is_new_file": False}, "Hello World Dashboard": {"type": "Dashboards", "description": "", "is_new_file": False}, "Hello World Connection": {"type": "Connections", "description": "", "is_new_file": False}, "Hello World Report": {"type": "Reports", "description": "", "is_new_file": False}, "N/A2": {"type": None, "description": "", "is_new_file": True}, } release_notes = update_rn.build_rn_template(changed_items) assert expected_result == release_notes
def test_find_corresponding_yml(self): """ Given: - a filepath containing a python file When: - determining the changed file Then: - return only the yml of the changed file """ expected_result = "Integration/HelloWorld.yml" from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) filepath = 'Integration/HelloWorld.py' filename = update_rn.find_corresponding_yml(filepath) assert expected_result == filename
def test_return_release_notes_path(self): """ Given: - a pack name and version When: - building the release notes file within the ReleaseNotes directory Then: - the filepath of the correct release notes. """ expected_result = 'Packs/HelloWorld/ReleaseNotes/1_1_1.md' from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) input_version = '1.1.1' result = update_rn.return_release_notes_path(input_version) assert expected_result == result
def format_user_input(self) -> Dict[str, str]: """ Replace the content item name with the content item display name if exists to match the template that being generated by the UpdateRN class by calling UpdateRN class function get_display_name(file_path) Build a dictionary with the release notes text per content item detected. Returns: Dict: Key is content item name, value is release note entry """ entity_identifier = '##### ' content_item_type_identifier = '#### ' rn_per_content_item: dict = defaultdict(str) entity_name = 'NonEntityRelated' items_path = { content_item.get('source_id'): content_item.get('source_file_name') for content_item in self.detected_content_items } for line in filter(None, self.release_notes.splitlines()): if line.startswith(entity_identifier): entity_name = line.lstrip(entity_identifier) if items_path.get(entity_name): entity_name = UpdateRN.get_display_name( items_path.get(entity_name)) elif not line.startswith(content_item_type_identifier): rn_per_content_item[entity_name] = rn_per_content_item[ entity_name] + line + '\n' return rn_per_content_item
def test_find_added_pack_files(self): """ Given: - List of added files When: - searching for relevant pack files Then: - return a list of relevant pack files which were added. """ from demisto_sdk.commands.update_release_notes.update_rn import \ UpdateRN added_files = {'HelloWorld/something_new.md', 'HelloWorld/test_data/nothing.md'} update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack=set(), added_files=added_files) update_rn.find_added_pack_files() assert update_rn.modified_files_in_pack == {'HelloWorld/something_new.md'}
def test_build_rn_template_when_only_pack_metadata_changed(self): """ Given: - an empty dict of changed items When: - we want to produce release notes template for a pack where only the pack_metadata file changed Then: - return a markdown string """ expected_result = "\n#### Integrations\n##### HelloWorld\n- Documentation and metadata improvements.\n" from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack=set(), added_files=set(), pack_metadata_only=True) changed_items = {} release_notes = update_rn.build_rn_template(changed_items) assert expected_result == release_notes
def are_release_notes_complete(self): is_valid = True modified_added_files = itertools.chain.from_iterable((self.added_files or [], self.modified_files or [])) if modified_added_files: for file in modified_added_files: if not any(permitted_type in file for permitted_type in VALIDATED_PACK_ITEM_TYPES): continue elif self.pack_name in file: update_rn_util = UpdateRN(pack=self.pack_name, pack_files=set(), update_type=None, added_files=set()) file_name, file_type = update_rn_util.identify_changed_file_type(file) if file_name and file_type: if (file_type not in self.latest_release_notes) or (file_name not in self.latest_release_notes): entity_name = update_rn_util.get_display_name(file) error_message, error_code = Errors.missing_release_notes_entry(file_type, self.pack_name, entity_name) if self.handle_error(error_message, error_code, self.file_path): is_valid = False return is_valid
def create_pack_release_notes(self, pack: str, filtered_modified_files: set, filtered_added_files: set, old_format_files: set): """ Creates the release notes for a given pack if was changed. :param pack: The pack to create release notes for filtered_modified_files: A set of filtered modified files filtered_added_files: A set of filtered added files old_format_files: A set of old formatted files """ existing_rn_version = self.get_existing_rn(pack) if existing_rn_version is None: # New release notes file already found for the pack raise RuntimeError(f"New release notes file already found for {pack}. " f"Please update manually or run `demisto-sdk update-release-notes " f"-i {pack}` without specifying the update_type.") pack_modified = filter_files_on_pack(pack, filtered_modified_files) pack_added = filter_files_on_pack(pack, filtered_added_files) pack_old = filter_files_on_pack(pack, old_format_files) # Checks if update is required if pack_modified or pack_added or pack_old or self.is_force: pack_path = pack_name_to_path(pack) update_pack_rn = UpdateRN(pack_path=pack_path, update_type=self.update_type, modified_files_in_pack=pack_modified.union(pack_old), pre_release=self.pre_release, added_files=pack_added, specific_version=self.specific_version, text=self.text, is_force=self.is_force, existing_rn_version_path=existing_rn_version, is_bc=self.is_bc) updated = update_pack_rn.execute_update() self.rn_path.append(update_pack_rn.rn_path) # If new release notes were created add it to the total number of packs that were updated. if updated: self.total_updated_packs.add(pack) # If there is an outdated previous release notes, remove it (for example: User updated his version to # 1.0.4 and meanwhile the master version changed to 1.0.4, so we want to remove the user's 1_0_4 file # and add a 1_0_5 file.) if update_pack_rn.should_delete_existing_rn: os.unlink(self.packs_existing_rn[pack]) else: print_warning(f'Either no changes were found in {pack} pack ' f'or the changes found should not be documented in the release notes file.\n' f'If relevant changes were made, please commit the changes and rerun the command.')
def test_ident_changed_file_type_release_notes(self): """ Given: - a filepath of a changed file When: - determining the type of item changed (e.g. Integration, Script, Layout, etc.) Then: - return tuple where first value is the pack name, and second is the item type """ expected_result = ('N/A', None) from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack="VulnDB", update_type='minor', pack_files={'HelloWorld'}, added_files=set()) filepath = os.path.join(TestRNUpdate.FILES_PATH, 'ReleaseNotes/1_0_1.md') result = update_rn.identify_changed_file_type(filepath) assert expected_result == result
def test_build_rn_template_playbook_modified_file(self): """ Given: - a dict of changed items When: - we want to produce a release notes template for modified file Then: - return a markdown string """ expected_result = "\n#### Playbooks\n##### Hello World Playbook\n- %%UPDATE_RN%%\n" from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) changed_items = { "Hello World Playbook": {"type": "Playbook", "description": "Hello World Playbook description", "is_new_file": False}, } release_notes = update_rn.build_rn_template(changed_items) assert expected_result == release_notes
def test_build_rn_template_file_without_description(self): """ Given: - a dict of changed items When: - we want to produce a release notes template for files without descriptions like : 'Connections', 'Incident Types', 'Indicator Types', 'Layouts', 'Incident Fields' Then: - return a markdown string """ expected_result = "\n#### Incident Fields\n- **Hello World IncidentField**\n" from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) changed_items = { "Hello World IncidentField": {"type": "Incident Fields", "description": "", "is_new_file": False}, } release_notes = update_rn.build_rn_template(changed_items) assert expected_result == release_notes
def test_check_for_release_notes_valid_file_path(self): """ Given: case 1: a description file case 2: an image file case 3: a non-image or description file When: running check_for_release_notes_valid_file_path method Then: case 1 & 2: change the file path to the corresponding yml file. case 3: file path remains unchnaged """ from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN image_file_path = "Packs/DNSDB/Integrations/DNSDB_v2/DNSDB_v2_image.png" description_file_path = "Packs/DNSDB/Integrations/DNSDB_v2/DNSDB_v2_description.md" yml_file_path = "Packs/DNSDB/Integrations/DNSDB_v2/DNSDB_v2.yml" assert yml_file_path == UpdateRN.check_for_release_notes_valid_file_path(image_file_path) assert yml_file_path == UpdateRN.check_for_release_notes_valid_file_path(description_file_path) assert yml_file_path == UpdateRN.check_for_release_notes_valid_file_path(yml_file_path)
def test_commit_to_bump(self): """ Given: - No inputs, but a condition where bumping the version is ready When: - running update Then: - update the metadata json by the version designated. """ ORIGINAL = os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/pack_metadata.json') TEMP_FILE = os.path.join(TestRNUpdate.FILES_PATH, 'fake_pack_invalid/_pack_metadata.json') from demisto_sdk.commands.update_release_notes.update_rn import UpdateRN update_rn = UpdateRN(pack_path="Packs/HelloWorld", update_type='minor', modified_files_in_pack={'HelloWorld'}, added_files=set()) shutil.copy(src=ORIGINAL, dst=TEMP_FILE) data_dict = get_json(TEMP_FILE) update_rn.metadata_path = TEMP_FILE update_rn.commit_to_bump(data_dict) os.remove(ORIGINAL) shutil.copy(src=TEMP_FILE, dst=ORIGINAL)