diff --git a/semantic_release/history/logs.py b/semantic_release/history/logs.py index e4d274847..955927718 100644 --- a/semantic_release/history/logs.py +++ b/semantic_release/history/logs.py @@ -6,7 +6,7 @@ from ..errors import UnknownCommitMessageStyleError from ..helpers import LoggedFunction from ..settings import config, current_commit_parser -from ..vcs_helpers import get_commit_log +from ..vcs_helpers import get_commit_log, get_formatted_commit logger = logging.getLogger(__name__) @@ -36,8 +36,9 @@ def evaluate_version_bump(current_version: str, force: str = None) -> Optional[s changes = [] commit_count = 0 + current_version_commit = get_formatted_commit(current_version) for _hash, commit_message in get_commit_log(current_version): - if commit_message.startswith(current_version): + if commit_message == current_version_commit: # Stop once we reach the current version # (we are looping in the order of newest -> oldest) logger.debug( @@ -67,7 +68,7 @@ def evaluate_version_bump(current_version: str, force: str = None) -> Optional[s if config.get("patch_without_tag") and commit_count > 0 and bump is None: bump = "patch" - logger.debug(f"Changing bump level to patch based on config patch_without_tag") + logger.debug("Changing bump level to patch based on config patch_without_tag") if ( not config.get("major_on_zero") @@ -81,7 +82,7 @@ def evaluate_version_bump(current_version: str, force: str = None) -> Optional[s @LoggedFunction(logger) -def generate_changelog(from_version: str, to_version: str = None) -> dict: +def generate_changelog(from_version: Optional[str], to_version: Optional[str] = None) -> dict: """ Parse a changelog dictionary for the given version. @@ -98,11 +99,13 @@ def generate_changelog(from_version: str, to_version: str = None) -> dict: rev = from_version found_the_release = to_version is None + to_version_commit = to_version and get_formatted_commit(to_version) + from_version_commit = from_version and get_formatted_commit(from_version) for _hash, commit_message in get_commit_log(rev): if not found_the_release: # Skip until we find the last commit in this release # (we are looping in the order of newest -> oldest) - if to_version and to_version not in commit_message: + if to_version_commit and commit_message != to_version_commit: continue else: logger.debug( @@ -110,7 +113,7 @@ def generate_changelog(from_version: str, to_version: str = None) -> dict: ) found_the_release = True - if from_version is not None and from_version in commit_message: + if from_version_commit and commit_message == from_version_commit: # We reached the previous release logger.debug(f"{from_version} reached, ending changelog generation") break diff --git a/semantic_release/vcs_helpers.py b/semantic_release/vcs_helpers.py index 5057021a5..8063e732c 100644 --- a/semantic_release/vcs_helpers.py +++ b/semantic_release/vcs_helpers.py @@ -37,6 +37,19 @@ def get_formatted_tag(version): return tag_format.format(version=version) +def get_formatted_commit(version: str) -> str: + commit_subject = config.get("commit_subject") + message = commit_subject.format(version=version) + + # Add an extended message if one is configured + commit_message = config.get("commit_message") + if commit_message: + message += "\n\n" + message += commit_message.format(version=version) + + return message + + def get_commit_log(from_rev=None): """Yield all commit messages from last to first.""" rev = None @@ -126,15 +139,7 @@ def commit_new_version(version: str): """ from .history import load_version_declarations - commit_subject = config.get("commit_subject") - message = commit_subject.format(version=version) - - # Add an extended message if one is configured - commit_message = config.get("commit_message") - if commit_message: - message += "\n\n" - message += commit_message.format(version=version) - + commit_message = get_formatted_commit(version) commit_author = config.get( "commit_author", "semantic-release ", @@ -144,7 +149,7 @@ def commit_new_version(version: str): git_path: PurePath = PurePath(os.getcwd(), declaration.path).relative_to(repo().working_dir) # type: ignore repo().git.add(str(git_path)) - return repo().git.commit(m=message, author=commit_author) + return repo().git.commit(m=commit_message, author=commit_author) @LoggedFunction(logger) diff --git a/tests/history/__init__.py b/tests/history/__init__.py index 43e02d9d7..316243646 100644 --- a/tests/history/__init__.py +++ b/tests/history/__init__.py @@ -37,5 +37,13 @@ ALL_KINDS_OF_COMMIT_MESSAGES = [MINOR, MAJOR, MINOR, PATCH] MINOR_AND_PATCH_COMMIT_MESSAGES = [MINOR, PATCH] PATCH_COMMIT_MESSAGES = [PATCH, PATCH] -MAJOR_LAST_RELEASE_MINOR_AFTER = [MINOR, ("22", "1.1.0"), MAJOR] -MAJOR_MENTIONING_LAST_VERSION = [MAJOR_MENTIONING_1_0_0, ("22", "1.0.0"), MAJOR] +MAJOR_LAST_RELEASE_MINOR_AFTER = [ + MINOR, + ("22", "1.1.0\n\nAutomatically generated by python-semantic-release"), + MAJOR +] +MAJOR_MENTIONING_LAST_VERSION = [ + MAJOR_MENTIONING_1_0_0, + ("22", "1.0.0\n\nAutomatically generated by python-semantic-release"), + MAJOR +] diff --git a/tests/history/test_version_bump.py b/tests/history/test_version_bump.py index 737643dc0..2f9f654f2 100644 --- a/tests/history/test_version_bump.py +++ b/tests/history/test_version_bump.py @@ -81,11 +81,7 @@ def test_should_return_none_without_commits(): """ Make sure that we do not release if there are no commits since last release. """ - with mock.patch("semantic_release.history.config.get", lambda *x: True): - assert evaluate_version_bump("1.1.0") is None - - with mock.patch("semantic_release.history.config.get", lambda *x: False): - assert evaluate_version_bump("1.1.0") is None + assert evaluate_version_bump("1.1.0") is None @mock.patch( @@ -94,3 +90,29 @@ def test_should_return_none_without_commits(): @mock.patch("semantic_release.history.logs.get_commit_log", lambda *a, **kw: [MAJOR]) def test_should_minor_without_major_on_zero(): assert evaluate_version_bump("0.1.0") == "minor" + +@mock.patch( + "semantic_release.history.config.get", wrapped_config_get( + commit_subject="chore(release): {version}", + commit_message="Custom message", + ) +) +@mock.patch( + "semantic_release.history.logs.get_commit_log", + lambda *a, **kw: [MINOR, ("777", "chore(release): 1.0.0\n\nCustom message"), MAJOR] +) +def test_should_search_for_release_with_commit_subject_pattern(): + assert evaluate_version_bump("1.0.0") == "minor" + +@mock.patch( + "semantic_release.history.config.get", wrapped_config_get( + commit_subject="chore(release): {version}", + commit_message="Custom message", + ) +) +@mock.patch( + "semantic_release.history.logs.get_commit_log", + lambda *a, **kw: [MINOR, ("777", "1.0.0"), MAJOR] +) +def test_should_not_search_for_release_without_commit_subject_pattern(): + assert evaluate_version_bump("1.0.0") == "major"