From 8455bab7468aa48c47823e573fba17b84674ce07 Mon Sep 17 00:00:00 2001 From: Dzmitry Ryzhykau Date: Mon, 11 Jul 2022 23:22:26 +0200 Subject: [PATCH] fix: prerelease tag in version patterns Delay construction of version and release patterns until runtime. This will allow to use non-default prerelease tag. --- semantic_release/history/__init__.py | 37 +++++++++++++++++++--------- semantic_release/vcs_helpers.py | 2 +- tests/history/test_version.py | 13 ++++++++++ tests/test_vcs_helpers.py | 22 ++++++++--------- 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/semantic_release/history/__init__.py b/semantic_release/history/__init__.py index 4a47c8b9d..ef6878c30 100644 --- a/semantic_release/history/__init__.py +++ b/semantic_release/history/__init__.py @@ -25,12 +25,18 @@ logger = logging.getLogger(__name__) -prerelease_pattern = f"-{config.get('prerelease_tag')}\.\d+" -version_pattern = f"(\d+\.\d+\.\d+({prerelease_pattern})?)" -release_version_pattern = f"(\d+\.\d+\.\d+(?!.*{prerelease_pattern}))" +def get_prerelease_pattern(): + return f"-{config.get('prerelease_tag')}\.\d+" -release_version_regex = rf"{release_version_pattern}" -version_regex = rf"{version_pattern}" + +def get_version_pattern(): + prerelease_pattern = get_prerelease_pattern() + return f"(\d+\.\d+\.\d+({prerelease_pattern})?)" + + +def get_release_version_pattern(): + prerelease_pattern = get_prerelease_pattern() + return f"(\d+\.\d+\.\d+(?!.*{prerelease_pattern}))" class VersionDeclaration(ABC): @@ -53,7 +59,8 @@ def from_variable(config_str: str): variable name. """ path, variable = config_str.split(":", 1) - pattern = rf'{variable} *[:=] *["\']{version_regex}["\']' + version_pattern = get_version_pattern() + pattern = rf'{variable} *[:=] *["\']{version_pattern}["\']' return PatternVersionDeclaration(path, pattern) @staticmethod @@ -63,7 +70,7 @@ def from_pattern(config_str: str): regular expression matching the version number. """ path, pattern = config_str.split(":", 1) - pattern = pattern.format(version=version_regex) + pattern = pattern.format(version=get_version_pattern()) return PatternVersionDeclaration(path, pattern) @abstractmethod @@ -187,7 +194,7 @@ def get_current_version_by_tag() -> str: :return: A string with the version number or 0.0.0 on failure. """ - version = get_last_version(pattern=version_pattern) + version = get_last_version(pattern=get_version_pattern()) if version: return version @@ -202,7 +209,7 @@ def get_current_release_version_by_tag() -> str: :return: A string with the version number or 0.0.0 on failure. """ - version = get_last_version(pattern=release_version_pattern) + version = get_last_version(pattern=get_release_version_pattern()) if version: return version @@ -333,6 +340,8 @@ def get_previous_version(version: str) -> Optional[str]: :param version: A string with the version number. :return: A string with the previous version number. """ + version_pattern = get_version_pattern() + found_version = False for commit_hash, commit_message in get_commit_log(): logger.debug(f"Checking commit {commit_hash}") @@ -342,7 +351,7 @@ def get_previous_version(version: str) -> Optional[str]: continue if found_version: - match = re.search(rf"{version_pattern}", commit_message) + match = re.search(version_pattern, commit_message) if match: logger.debug(f"Version matches regex {commit_message}") return match.group(1).strip() @@ -360,6 +369,8 @@ def get_previous_release_version(version: str) -> Optional[str]: :param version: A string with the version number. :return: A string with the previous version number. """ + release_version_pattern = get_release_version_pattern() + found_version = False for commit_hash, commit_message in get_commit_log(): logger.debug(f"Checking commit {commit_hash}") @@ -369,7 +380,7 @@ def get_previous_release_version(version: str) -> Optional[str]: continue if found_version: - match = re.search(rf"{release_version_pattern}", commit_message) + match = re.search(release_version_pattern, commit_message) if match: logger.debug(f"Version matches regex {commit_message}") return match.group(1).strip() @@ -386,9 +397,11 @@ def get_current_release_version_by_commits() -> str: :return: A string with the current version number. """ + release_version_re = re.compile(get_release_version_pattern()) + for commit_hash, commit_message in get_commit_log(): logger.debug(f"Checking commit {commit_hash}") - match = re.search(rf"{release_version_pattern}", commit_message) + match = release_version_re.search(commit_message) if match: logger.debug(f"Version matches regex {commit_message}") return match.group(1).strip() diff --git a/semantic_release/vcs_helpers.py b/semantic_release/vcs_helpers.py index cdfb1ae2f..5cb8ebe52 100644 --- a/semantic_release/vcs_helpers.py +++ b/semantic_release/vcs_helpers.py @@ -80,7 +80,7 @@ def version_finder(tag): if i.name in skip_tags: continue - match = re.search(rf"{pattern}", i.name) + match = re.search(pattern, i.name) if match: return match.group(0).strip() diff --git a/tests/history/test_version.py b/tests/history/test_version.py index f62b2d513..f251a7fee 100644 --- a/tests/history/test_version.py +++ b/tests/history/test_version.py @@ -461,6 +461,19 @@ def test_toml_replace(self, tmp_path, key, old_content, new_content): (Path("path2"), r'var2 *[:=] *["\'](\d+\.\d+\.\d+(-beta\.\d+)?)["\']'), ], ), + dict( + pyproject="""\ + [tool.semantic_release] + version_variable = "path:__version__" + prerelease_tag = "alpha" + """, + patterns=[ + ( + Path("path"), + r'__version__ *[:=] *["\'](\d+\.\d+\.\d+(-alpha\.\d+)?)["\']', + ), + ], + ), dict( pyproject="""\ [tool.semantic_release] diff --git a/tests/test_vcs_helpers.py b/tests/test_vcs_helpers.py index 5a583a870..392556eea 100644 --- a/tests/test_vcs_helpers.py +++ b/tests/test_vcs_helpers.py @@ -6,7 +6,7 @@ from git import GitCommandError, Repo, TagObject from semantic_release.errors import GitError, HvcsRepoParseError -from semantic_release.history import release_version_pattern, version_pattern +from semantic_release.history import get_release_version_pattern, get_version_pattern from semantic_release.vcs_helpers import ( check_repo, checkout, @@ -396,22 +396,22 @@ def __init__(self, name, sha, date, is_tag_object): @pytest.mark.parametrize( - "pattern, skip_tags,expected_result", + "get_pattern, skip_tags,expected_result", [ - (version_pattern, None, "2.1.0-beta.0"), - (version_pattern, ["v2.1.0-beta.0"], "2.0.0"), - (version_pattern, ["v2.1.0-beta.0", "v2.0.0-beta.0", "v2.0.0"], "1.1.0"), + (get_version_pattern, None, "2.1.0-beta.0"), + (get_version_pattern, ["v2.1.0-beta.0"], "2.0.0"), + (get_version_pattern, ["v2.1.0-beta.0", "v2.0.0-beta.0", "v2.0.0"], "1.1.0"), ( - version_pattern, + get_version_pattern, ["v2.1.0-beta.0", "v2.0.0-beta.0", "v0.1.0", "v1.0.0", "v1.1.0", "v2.0.0"], None, ), - (release_version_pattern, None, "2.0.0"), - (release_version_pattern, ["v2.0.0"], "1.1.0"), - (release_version_pattern, ["v2.0.0", "v1.1.0", "v1.0.0", "v0.1.0"], None), + (get_release_version_pattern, None, "2.0.0"), + (get_release_version_pattern, ["v2.0.0"], "1.1.0"), + (get_release_version_pattern, ["v2.0.0", "v1.1.0", "v1.0.0", "v0.1.0"], None), ], ) -def test_get_last_version_with_real_pattern(pattern, skip_tags, expected_result): +def test_get_last_version_with_real_pattern(get_pattern, skip_tags, expected_result): # TODO: add some prerelease tags class FakeCommit: def __init__(self, com_date): @@ -442,7 +442,7 @@ def __init__(self, name, sha, date, is_tag_object): FakeTag("v1.0.0", "bbbbbbbbbbbbbbbbbbbb", 2, False), ] ) - assert expected_result == get_last_version(pattern, skip_tags) + assert expected_result == get_last_version(get_pattern(), skip_tags) def test_update_changelog_file_ok(mock_git, mocker):