def test_commit_grouping_by_action_and_scope(self, commit_list): semantic_commits = commit_analyzer(commit_list, label_pattern="!{type}:{scope}") release_data = ReleaseDataTree(semantic_commits) assert len(release_data["fix"]["thing"]) == 1 assert len(release_data["feat"]["scopeless"]) == 1 assert len(release_data["feat"]["cli"]) == 1 assert len(release_data["feat"]["music"]) == 2 assert len(release_data["refactor"]["music"]) == 1 assert len(release_data["refactor"]["lorem"]) == 1
def test_release_with_fixes(self, commit_registry): semantic_commits = commit_analyzer([commit_registry["4d17c1a"]], label_pattern="!{type}:{scope}") release_data = ReleaseDataTree(semantic_commits) version = Version(major=10, minor=3, patch=0) markup = _render_release(version, release_data=release_data) assert markup == (f"10.3.0 ({str(date.today())})\n" "-------------------\n\n" "Bug Fixes\n" "~~~~~~~~~\n\n" "* thing - Fix a thing\n\n")
def test_scopeless_label_pattern(self, isolated_filesystem): commit = self.Commit(header="Make it work", footer="!fix", message="") with isolated_filesystem: lst = commit_analyzer([commit], label_pattern="!{type}", label_position="footer") assert len(lst) == 1 assert lst[0].subject == "Make it work" assert lst[0].scope is None assert lst[0].type == "fix"
def test_label_in_header(self, isolated_filesystem, label_pattern, header): commit = self.Commit(header=header, footer=None, message="") with isolated_filesystem: lst = commit_analyzer([commit], label_pattern=label_pattern, label_position="header") assert len(lst) == 1 assert lst[0].subject == "Make it work" assert lst[0].scope == "cli" assert lst[0].type == "fix"
def test_release_with_features(self, commit_registry): reg = commit_registry version = Version(major=10, minor=3, patch=0) semantic_commits = commit_analyzer( [reg["ccaa185"], reg["bc0bcab"], reg["a6b655f"]], label_pattern="!{type}:{scope}", ) release_data = ReleaseDataTree(semantic_commits) markup = _render_release(version, release_data=release_data) assert markup == (f"10.3.0 ({str(date.today())})\n" "-------------------\n\n" "Features\n" "~~~~~~~~\n\n" "* Add a thing\n" "* music - Add more music please\n" "* cli - Add a cli tool\n\n")
def test_release_with_fixes_and_features(self, commit_list): version = Version(major=10, minor=3, patch=0) semantic_commits = commit_analyzer(commit_list, label_pattern="!{type}:{scope}") release_data = ReleaseDataTree(semantic_commits) markup = _render_release(version, release_data=release_data) assert markup == (f"10.3.0 ({str(date.today())})\n" "-------------------\n\n" "Bug Fixes\n" "~~~~~~~~~\n\n" "* thing - Fix a thing\n\n" "Features\n" "~~~~~~~~\n\n" "* Add a thing\n" "* music\n\n" " - Add more music please\n" " - Add cool musics :D\n" "* cli - Add a cli tool\n\n")
def release( ctx, bump, bump_type, commit_flag, message, tag_flag, confirm_flag, changelog_file, files, label_pattern, label_position, tag_pattern, current_version, stage, merge_pre, current_tag=None, versions=None, ): """Release a new version. Determines the next version by inspecting commit messages, updates the changelog, commit the changes and tag the repository with the new version. """ # If there isn't a current version, assume version 0.0.0 current_version = current_version or Version() git = Git() from_tag = current_tag.name if current_tag else None # Delimiter of the block to be removed from the changelog file remove_pre_chglog = None # Look for the last final release version if the user want it if merge_pre and current_version.stage != "final": remove_pre_chglog = [current_version.string] for version in versions: if version.stage == "final": from_tag = version.tag.name remove_pre_chglog.append(version.string) break commit_list = git.log(_from=from_tag) msg(f'{label("Current version")} {current_version}') msg(f'{label("Commits found")} {len(commit_list)} since last release') if not commit_list: click.echo(" › Nothing to release.") ctx.exit() semantic_commits = commit_analyzer(commit_list, label_pattern, label_position) release_data = ReleaseDataTree(semantic_commits) bump_version_to = None # --bump, --major, --minor, --patch or commit message based version # are taken into account only if the current version is in final stage. if current_version.stage == "final": # --bump have precedence over any of --major, --minor or --patch bump_version_to = bump.string if bump else bump_type # Any manual bump have precedence over commit message based versions. bump_version_to = bump_version_to or release_data.bump_version_to try: new_version = get_next_version(current_version, bump_version_to, stage) except ValueError as e: ctx.fail(e) if not new_version: msg("The release of a lower versions is not supported for now.") ctx.abort() new_tag_name = tag_pattern.format(version=new_version.string) msg(f'{label("New version")} {new_version}') msg(f'{label("Changelog file")} {changelog_file.name}') # Messages about what tasks will be performed msg("Braulio will perform the next tasks :") msg(f" Update {len(files) + 1} files.", prefix="") msg(" Add a release commit.", prefix="", silence=not commit_flag) msg( f" Tag the repository with {new_tag_name}", prefix="", silence=not tag_flag, ) msg("", prefix="") # Print just a new line if confirm_flag or click.confirm(f"{prefix_mark}Continue?"): msg("Update changelog ", nl=False) update_chglog( changelog_file, new_version=new_version, current_version=current_version, release_data=release_data, remove=remove_pre_chglog, ) msg(check_mark, prefix="") try: update_files(files, str(current_version), str(new_version)) except ValueError as e: click.echo(e) ctx.abort() if commit_flag: message_args = {"new_version": new_version.string} if "{current_version}" in message: message_args["current_version"] = current_version.string commit_message = message.format(**message_args) msg(f"Add commit: {commit_message}", nl=False) files = [str(changelog_file)] + list(files) git.commit(commit_message, files=files) msg(f" {check_mark}", prefix="") if tag_flag: msg(f"Add tag {new_tag_name}", nl=False) git.tag(new_tag_name) msg(f" {check_mark}", prefix="") if "current_version" in ctx.obj.cfg_file_options: update_config_file("current_version", new_version.string) msg(f"Version {new_version} released successfully", suffix=" 🎉")