diff --git a/release_management/_utils.py b/release_management/_utils.py index dd1d5e3..b2f4297 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -23,11 +23,13 @@ import tomllib from datetime import datetime from getpass import getpass +from typing import Any from urllib.parse import urlparse # isort: THIRDPARTY import requests from github import Github +from semantic_version import Version from specfile import specfile MANIFEST_PATH = "./Cargo.toml" @@ -38,25 +40,26 @@ class ReleaseVersion: # pylint: disable=too-few-public-methods Release version for the package. """ - def __init__(self, base, *, prerelease=None): + def __init__(self, base: Version, *, pre: bool = False, post: bool = False): """ Initializer. - :param str base: Base version - :param prerelease: pre-release - :type prerelease: str or Nonetype + :param Version base: Base version + :param bool pre: whether or not this is a pre-release """ + assert not (pre and post), "Impossible for a release to be pre- and post-" self.base = base - self.prerelease = prerelease + self.pre = pre + self.post = post def __str__(self): - return f"{self.base}{'' if self.prerelease is None else '~' + self.prerelease}" + return f"{self.base}{'~pre' if self.pre else ''}{'^post' if self.post else ''}" -def calc_release_suffix(): +def release_stamp() -> str: """ - Return a standard value for the release suffix for the version + Return a release stamp. Should be unique to the second. :rtype: str - :returns: standard pre-release suffix + :returns: a release stamp for modifying releases """ command = ["git", "rev-parse", "--short=8", "HEAD"] with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: @@ -83,6 +86,7 @@ def edit_specfile(specfile_path, *, release_version=None, sources=None, arbitrar with specfile.Specfile(specfile_path) as spec: if release_version is not None: spec.version = str(release_version) + spec.release = release_stamp() if sources is not None: with spec.sources() as entries: # pylint: disable=not-context-manager for index, value in enumerate(sources): @@ -91,12 +95,12 @@ def edit_specfile(specfile_path, *, release_version=None, sources=None, arbitrar arbitrary(spec) -def get_python_package_info(name): +def get_python_package_info(name) -> tuple[Version, Any]: """ Get info about the python package. :param str name: the project name - :returns: str * ParseResult + :returns: Version * ParseResult """ command = ["python3", "setup.py", "--name"] with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: @@ -109,7 +113,7 @@ def get_python_package_info(name): command = ["python3", "setup.py", "--version"] with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: - release_version = ( + release_version = Version( proc.stdout.readline() # pyright: ignore [ reportOptionalMemberAccess ] .strip() .decode("utf-8") @@ -128,14 +132,14 @@ def get_python_package_info(name): return (release_version, github_repo) -def get_package_info(manifest_abs_path, package_name): +def get_package_info(manifest_abs_path, package_name) -> tuple[Version, Any]: """ Extract the version string and repo URL from Cargo.toml and return it. :param str manifest_path: absolute path to a Cargo.toml file :param str package_name: the expected name of the package :returns: stratisd version string and repository URL - :rtype: str * ParseResult + :rtype: Version * ParseResult """ assert os.path.isabs(manifest_abs_path) @@ -149,7 +153,7 @@ def get_package_info(manifest_abs_path, package_name): ) github_repo = urlparse(package["repository"].rstrip("/")) assert github_repo.netloc == "github.com", "specified repo is not on GitHub" - return (package["version"], github_repo) + return (Version(package["version"]), github_repo) def verify_tag(tag): diff --git a/release_management/create_artifacts.py b/release_management/create_artifacts.py index aa1a6b2..b8a0248 100755 --- a/release_management/create_artifacts.py +++ b/release_management/create_artifacts.py @@ -26,7 +26,6 @@ from _utils import ( MANIFEST_PATH, ReleaseVersion, - calc_release_suffix, edit_specfile, get_package_info, get_python_package_info, @@ -61,12 +60,18 @@ def main(): help="path to specfile to edit", type=lambda p: p if p is None else os.path.abspath(p), ) - parser.add_argument( + + pre_or_post = parser.add_mutually_exclusive_group(required=False) + pre_or_post.add_argument( "--pre-release", action="store_true", - default=False, help="do automatic actions for a pre-release version", ) + pre_or_post.add_argument( + "--post-release", + action="store_true", + help="do automatic actions for a post-release version", + ) subparsers = parser.add_subparsers(title="subcommands") @@ -113,13 +118,13 @@ def _stratisd_artifacts(namespace): (source_version, _) = get_package_info(manifest_abs_path, "stratisd") - pre_release_suffix = calc_release_suffix() if namespace.pre_release else None - specfile_path = namespace.specfile_path - if specfile_path is None and pre_release_suffix is not None: + if specfile_path is None and (namespace.pre_release or namespace.post_release): raise RuntimeError("must specify specfile using --specfile-path option") - release_version = ReleaseVersion(source_version, prerelease=pre_release_suffix) + release_version = ReleaseVersion( + source_version, pre=namespace.pre_release, post=namespace.post_release + ) filtered = namespace.vendor_method == "filtered" @@ -157,13 +162,14 @@ def _stratis_cli_artifacts(namespace): (source_version, _) = get_python_package_info("stratis-cli") - pre_release_suffix = calc_release_suffix() if namespace.pre_release else None specfile_path = namespace.specfile_path - if specfile_path is None and pre_release_suffix is not None: + if specfile_path is None and (namespace.pre_release or namespace.post_release): raise RuntimeError("must specify specfile using --specfile-path option") - release_version = ReleaseVersion(source_version, prerelease=pre_release_suffix) + release_version = ReleaseVersion( + source_version, pre=namespace.pre_release, post=namespace.post_release + ) source_tarfile = make_source_tarball( "stratis-cli",