From 35f413ca546a1802c939b0ef36c4a1e334e84b92 Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 2 Jun 2025 21:03:53 -0400 Subject: [PATCH 1/7] Use Version constructor for versions --- release_management/_utils.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/release_management/_utils.py b/release_management/_utils.py index dd1d5e3..f8d73c0 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,10 +40,10 @@ class ReleaseVersion: # pylint: disable=too-few-public-methods Release version for the package. """ - def __init__(self, base, *, prerelease=None): + def __init__(self, base: Version, *, prerelease=None): """ Initializer. - :param str base: Base version + :param Version base: Base version :param prerelease: pre-release :type prerelease: str or Nonetype """ @@ -91,12 +93,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 +111,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 +130,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 +151,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): From b8623df38be659da1f6f23925033b774ec03b2c0 Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 2 Jun 2025 21:13:10 -0400 Subject: [PATCH 2/7] Just use "pre" for the pre-release suffix Signed-off-by: mulhern --- release_management/_utils.py | 17 ----------------- release_management/create_artifacts.py | 5 ++--- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/release_management/_utils.py b/release_management/_utils.py index f8d73c0..70514ac 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -21,7 +21,6 @@ import os import subprocess import tomllib -from datetime import datetime from getpass import getpass from typing import Any from urllib.parse import urlparse @@ -54,22 +53,6 @@ def __str__(self): return f"{self.base}{'' if self.prerelease is None else '~' + self.prerelease}" -def calc_release_suffix(): - """ - Return a standard value for the release suffix for the version - :rtype: str - :returns: standard pre-release suffix - """ - command = ["git", "rev-parse", "--short=8", "HEAD"] - with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: - commit_hash = ( - proc.stdout.readline() # pyright: ignore [ reportOptionalMemberAccess ] - .strip() - .decode("utf-8") - ) - return f"{datetime.today():%Y%m%d%H%M}git{commit_hash}" - - def edit_specfile(specfile_path, *, release_version=None, sources=None, arbitrary=None): """ Edit the specfile in place diff --git a/release_management/create_artifacts.py b/release_management/create_artifacts.py index aa1a6b2..28c06b8 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, @@ -113,7 +112,7 @@ 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 + pre_release_suffix = "pre" if namespace.pre_release else None specfile_path = namespace.specfile_path if specfile_path is None and pre_release_suffix is not None: @@ -157,7 +156,7 @@ 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 + pre_release_suffix = "pre" if namespace.pre_release else None specfile_path = namespace.specfile_path if specfile_path is None and pre_release_suffix is not None: From b35f7f6b42d75b22e97d166028839371a446667a Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 2 Jun 2025 21:19:56 -0400 Subject: [PATCH 3/7] Use a boolean to indicate pre-release The pre-release value can be calculated in the ReleaseVersion class. Signed-off-by: mulhern --- release_management/_utils.py | 9 ++++----- release_management/create_artifacts.py | 11 ++++------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/release_management/_utils.py b/release_management/_utils.py index 70514ac..e902b9b 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -39,18 +39,17 @@ class ReleaseVersion: # pylint: disable=too-few-public-methods Release version for the package. """ - def __init__(self, base: Version, *, prerelease=None): + def __init__(self, base: Version, *, pre: bool = False): """ Initializer. :param Version base: Base version - :param prerelease: pre-release - :type prerelease: str or Nonetype + :param bool pre: whether or not this is a pre-release """ self.base = base - self.prerelease = prerelease + self.pre = pre def __str__(self): - return f"{self.base}{'' if self.prerelease is None else '~' + self.prerelease}" + return f"{self.base}{'~pre' if self.pre else ''}" def edit_specfile(specfile_path, *, release_version=None, sources=None, arbitrary=None): diff --git a/release_management/create_artifacts.py b/release_management/create_artifacts.py index 28c06b8..3f06870 100755 --- a/release_management/create_artifacts.py +++ b/release_management/create_artifacts.py @@ -112,13 +112,11 @@ def _stratisd_artifacts(namespace): (source_version, _) = get_package_info(manifest_abs_path, "stratisd") - pre_release_suffix = "pre" 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: 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) filtered = namespace.vendor_method == "filtered" @@ -156,13 +154,12 @@ def _stratis_cli_artifacts(namespace): (source_version, _) = get_python_package_info("stratis-cli") - pre_release_suffix = "pre" 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: 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) source_tarfile = make_source_tarball( "stratis-cli", From 0ef71ef335e54a6ded160077c4d48c0385ce6ccb Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 2 Jun 2025 21:26:19 -0400 Subject: [PATCH 4/7] Add post argument to ReleaseVersion constructor Signed-off-by: mulhern --- release_management/_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/release_management/_utils.py b/release_management/_utils.py index e902b9b..4428c99 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -39,17 +39,19 @@ class ReleaseVersion: # pylint: disable=too-few-public-methods Release version for the package. """ - def __init__(self, base: Version, *, pre: bool = False): + def __init__(self, base: Version, *, pre: bool = False, post: bool = False): """ Initializer. :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.pre = pre + self.post = post def __str__(self): - return f"{self.base}{'~pre' if self.pre else ''}" + return f"{self.base}{'~pre' if self.pre else ''}{'^post' if self.post else ''}" def edit_specfile(specfile_path, *, release_version=None, sources=None, arbitrary=None): From 2436b5dd73b87a3781cc8935eb2472915970e848 Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 2 Jun 2025 21:42:18 -0400 Subject: [PATCH 5/7] Add --post-release option to create_artifacts.py Signed-off-by: mulhern --- release_management/create_artifacts.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/release_management/create_artifacts.py b/release_management/create_artifacts.py index 3f06870..b8a0248 100755 --- a/release_management/create_artifacts.py +++ b/release_management/create_artifacts.py @@ -60,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,10 +119,12 @@ def _stratisd_artifacts(namespace): (source_version, _) = get_package_info(manifest_abs_path, "stratisd") specfile_path = namespace.specfile_path - if specfile_path is None and namespace.pre_release: + 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, pre=namespace.pre_release) + release_version = ReleaseVersion( + source_version, pre=namespace.pre_release, post=namespace.post_release + ) filtered = namespace.vendor_method == "filtered" @@ -156,10 +164,12 @@ def _stratis_cli_artifacts(namespace): specfile_path = namespace.specfile_path - if specfile_path is None and namespace.pre_release: + 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, pre=namespace.pre_release) + release_version = ReleaseVersion( + source_version, pre=namespace.pre_release, post=namespace.post_release + ) source_tarfile = make_source_tarball( "stratis-cli", From ff0f399dcb71153724d90b9829fccac632b821d7 Mon Sep 17 00:00:00 2001 From: mulhern Date: Tue, 3 Jun 2025 09:10:36 -0400 Subject: [PATCH 6/7] Add a release_stamp() method Signed-off-by: mulhern --- release_management/_utils.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/release_management/_utils.py b/release_management/_utils.py index 4428c99..cae30b0 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -21,6 +21,7 @@ import os import subprocess import tomllib +from datetime import datetime from getpass import getpass from typing import Any from urllib.parse import urlparse @@ -54,6 +55,22 @@ def __str__(self): return f"{self.base}{'~pre' if self.pre else ''}{'^post' if self.post else ''}" +def release_stamp() -> str: + """ + Return a release stamp. Should be unique to the second. + :rtype: str + :returns: a release stamp for modifying releases + """ + command = ["git", "rev-parse", "--short=8", "HEAD"] + with subprocess.Popen(command, stdout=subprocess.PIPE) as proc: + commit_hash = ( + proc.stdout.readline() # pyright: ignore [ reportOptionalMemberAccess ] + .strip() + .decode("utf-8") + ) + return f"{datetime.today():%Y%m%d%H%M}git{commit_hash}" + + def edit_specfile(specfile_path, *, release_version=None, sources=None, arbitrary=None): """ Edit the specfile in place From cd446971cf7ea4e2d4d6a425dbbff8e514baeb4a Mon Sep 17 00:00:00 2001 From: mulhern Date: Tue, 3 Jun 2025 09:27:41 -0400 Subject: [PATCH 7/7] Also include release stamp if release-version is not None Signed-off-by: mulhern --- release_management/_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/release_management/_utils.py b/release_management/_utils.py index cae30b0..b2f4297 100755 --- a/release_management/_utils.py +++ b/release_management/_utils.py @@ -86,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):