-
Notifications
You must be signed in to change notification settings - Fork 255
Fix/Refactor: Prerelease #435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1ebfc11
d8b443e
3e3963b
f958968
5c270ea
73059ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,14 @@ | |
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}))" | ||
|
||
release_version_regex = rf"{release_version_pattern}" | ||
version_regex = rf"{version_pattern}" | ||
|
||
|
||
class VersionDeclaration(ABC): | ||
def __init__(self, path: Union[str, Path]): | ||
self.path = Path(path) | ||
|
@@ -46,7 +54,7 @@ def from_variable(config_str: str): | |
""" | ||
path, variable = config_str.split(":", 1) | ||
pattern = ( | ||
rf'{variable} *[:=] *["\']{PatternVersionDeclaration.version_regex}["\']' | ||
rf'{variable} *[:=] *["\']{version_regex}["\']' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. replaced to use a single source of truth |
||
) | ||
return PatternVersionDeclaration(path, pattern) | ||
|
||
|
@@ -57,7 +65,7 @@ def from_pattern(config_str: str): | |
regular expression matching the version number. | ||
""" | ||
path, pattern = config_str.split(":", 1) | ||
pattern = pattern.format(version=PatternVersionDeclaration.version_regex) | ||
pattern = pattern.format(version=version_regex) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. replaced to use a single source of truth |
||
return PatternVersionDeclaration(path, pattern) | ||
|
||
@abstractmethod | ||
|
@@ -116,8 +124,6 @@ class PatternVersionDeclaration(VersionDeclaration): | |
function to create the version patterns specified in the config files. | ||
""" | ||
|
||
version_regex = r"(\d+\.\d+(?:\.\d+)?)" | ||
|
||
# The pattern should be a regular expression with a single group, | ||
# containing the version to replace. | ||
def __init__(self, path: str, pattern: str): | ||
|
@@ -176,18 +182,29 @@ def swap_version(m): | |
self.path.write_text(new_content) | ||
|
||
|
||
def get_prerelease_pattern() -> str: | ||
return "-" + config.get("prerelease_tag") + "." | ||
@LoggedFunction(logger) | ||
def get_current_version_by_tag() -> str: | ||
""" | ||
Find the current version of the package in the current working directory using git tags. | ||
|
||
:return: A string with the version number or 0.0.0 on failure. | ||
""" | ||
version = get_last_version(pattern=version_pattern) | ||
if version: | ||
return version | ||
|
||
logger.debug("no version found, returning default of v0.0.0") | ||
return "0.0.0" | ||
|
||
|
||
@LoggedFunction(logger) | ||
def get_current_version_by_tag(omit_pattern=None) -> str: | ||
def get_current_release_version_by_tag() -> str: | ||
""" | ||
Find the current version of the package in the current working directory using git tags. | ||
|
||
:return: A string with the version number or 0.0.0 on failure. | ||
""" | ||
version = get_last_version(omit_pattern=omit_pattern) | ||
version = get_last_version(pattern=release_version_pattern) | ||
if version: | ||
return version | ||
|
||
|
@@ -196,7 +213,7 @@ def get_current_version_by_tag(omit_pattern=None) -> str: | |
|
||
|
||
@LoggedFunction(logger) | ||
def get_current_version_by_config_file(omit_pattern=None) -> str: | ||
def get_current_version_by_config_file() -> str: | ||
""" | ||
Get current version from the version variable defined in the configuration. | ||
|
||
|
@@ -220,25 +237,36 @@ def get_current_version_by_config_file(omit_pattern=None) -> str: | |
return version | ||
|
||
|
||
def get_current_version(prerelease_version: bool = False) -> str: | ||
def get_current_version() -> str: | ||
""" | ||
Get current version from tag or version variable, depending on configuration. | ||
This will not return prerelease versions. | ||
This can be either a release or prerelease version | ||
|
||
:return: A string with the current version number | ||
""" | ||
omit_pattern = None if prerelease_version else get_prerelease_pattern() | ||
if config.get("version_source") in ["tag", "tag_only"]: | ||
return get_current_version_by_tag(omit_pattern) | ||
current_version = get_current_version_by_config_file(omit_pattern) | ||
if omit_pattern and omit_pattern in current_version: | ||
return get_previous_version(current_version) | ||
return current_version | ||
return get_current_version_by_tag() | ||
else: | ||
return get_current_version_by_config_file() | ||
|
||
|
||
def get_current_release_version() -> str: | ||
""" | ||
Get current release version from tag or commit message (no going back in config file), | ||
depending on configuration. | ||
This will return the current release version (NOT prerelease), instead of just the current version | ||
|
||
:return: A string with the current version number | ||
""" | ||
if config.get("version_source") == "tag": | ||
return get_current_release_version_by_tag() | ||
else: | ||
return get_current_release_version_by_commits() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
|
||
@LoggedFunction(logger) | ||
def get_new_version( | ||
current_version: str, level_bump: str, prerelease: bool = False | ||
current_version: str, current_release_version: str, level_bump: str, prerelease: bool = False | ||
) -> str: | ||
""" | ||
Calculate the next version based on the given bump level with semver. | ||
|
@@ -249,34 +277,46 @@ def get_new_version( | |
:param prerelease: Should the version bump be marked as a prerelease | ||
:return: A string with the next version number. | ||
""" | ||
if not level_bump: | ||
logger.debug("No bump requested, using input version") | ||
new_version = current_version | ||
# pre or release version | ||
current_version_info = semver.VersionInfo.parse(current_version) | ||
# release version | ||
current_release_version_info = semver.VersionInfo.parse(current_release_version) | ||
|
||
# sanity check | ||
# if the current version is no prerelease, than | ||
# current_version and current_release_version must be the same | ||
if not current_version_info.prerelease and current_version_info.compare(current_release_version_info) != 0: | ||
raise ValueError() | ||
|
||
if level_bump: | ||
next_version_info = current_release_version_info.next_version(level_bump) | ||
elif prerelease: | ||
# we do at least a patch for prereleases | ||
next_version_info = current_release_version_info.next_version("patch") | ||
else: | ||
new_version = str( | ||
semver.VersionInfo.parse(current_version).next_version(part=level_bump) | ||
) | ||
next_version_info = current_release_version_info | ||
|
||
if prerelease: | ||
logger.debug("Prerelease requested") | ||
potentialy_prereleased_current_version = get_current_version( | ||
prerelease_version=True | ||
) | ||
if get_prerelease_pattern() in potentialy_prereleased_current_version: | ||
logger.debug("Previouse prerelease detected, increment prerelease version") | ||
prerelease_num = ( | ||
int(potentialy_prereleased_current_version.split(".")[-1]) + 1 | ||
) | ||
next_raw_version = next_version_info.to_tuple()[:3] | ||
current_raw_version = current_version_info.to_tuple()[:3] | ||
|
||
if current_version_info.prerelease and next_raw_version == current_raw_version: | ||
# next version (based on commits) matches current prerelease version | ||
# bump prerelase | ||
next_prerelease_version_info = current_version_info.bump_prerelease(config.get("prerelease_tag")) | ||
else: | ||
logger.debug("No previouse prerelease detected, starting from 0") | ||
prerelease_num = 0 | ||
new_version = new_version + get_prerelease_pattern() + str(prerelease_num) | ||
# next version (based on commits) higher than current prerelease version | ||
# new prerelease based on next version | ||
next_prerelease_version_info = next_version_info.bump_prerelease(config.get("prerelease_tag")) | ||
|
||
return new_version | ||
return str(next_prerelease_version_info) | ||
else: | ||
# normal version bump | ||
return str(next_version_info) | ||
|
||
|
||
@LoggedFunction(logger) | ||
def get_previous_version(version: str, omit_pattern: str = None) -> Optional[str]: | ||
def get_previous_version(version: str) -> Optional[str]: | ||
""" | ||
Return the version prior to the given version. | ||
|
||
|
@@ -292,16 +332,55 @@ def get_previous_version(version: str, omit_pattern: str = None) -> Optional[str | |
continue | ||
|
||
if found_version: | ||
if omit_pattern and omit_pattern in commit_message: | ||
continue | ||
matches = re.match(r"v?(\d+.\d+.\d+)", commit_message) | ||
if matches: | ||
match = re.search(rf"{version_pattern}", commit_message) | ||
if match: | ||
logger.debug(f"Version matches regex {commit_message}") | ||
return matches.group(1).strip() | ||
return match.group(1).strip() | ||
|
||
return get_last_version(pattern=version_pattern, skip_tags=[version, get_formatted_tag(version)]) | ||
|
||
|
||
return get_last_version( | ||
[version, get_formatted_tag(version)], omit_pattern=omit_pattern | ||
) | ||
@LoggedFunction(logger) | ||
def get_previous_release_version(version: str) -> Optional[str]: | ||
""" | ||
Return the version prior to the given version. | ||
|
||
:param version: A string with the version number. | ||
:return: A string with the previous version number. | ||
""" | ||
found_version = False | ||
for commit_hash, commit_message in get_commit_log(): | ||
logger.debug(f"Checking commit {commit_hash}") | ||
if version in commit_message: | ||
found_version = True | ||
logger.debug(f'Found version in commit "{commit_message}"') | ||
continue | ||
|
||
if found_version: | ||
match = re.search(rf"{release_version_pattern}", commit_message) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. replaced to use a single source of truth |
||
if match: | ||
logger.debug(f"Version matches regex {commit_message}") | ||
return match.group(1).strip() | ||
|
||
return get_last_version(pattern=release_version_pattern, skip_tags=[version, get_formatted_tag(version)]) | ||
|
||
|
||
@LoggedFunction(logger) | ||
def get_current_release_version_by_commits() -> str: | ||
""" | ||
Return the current release version (NOT prerelease) version. | ||
|
||
:return: A string with the current version number. | ||
""" | ||
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) | ||
if match: | ||
logger.debug(f"Version matches regex {commit_message}") | ||
return match.group(1).strip() | ||
|
||
# nothing found, return the initial version | ||
return "0.0.0" | ||
|
||
|
||
@LoggedFunction(logger) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this variables as single source of truth for regex version matching, for ease of use once as string and once as regex.