From bd438a648c331a6d51b287fec140490bb929b023 Mon Sep 17 00:00:00 2001 From: Massimiliano Date: Thu, 30 Nov 2023 18:01:39 +0100 Subject: [PATCH] Fix version format (infra) (#856) * Implement output-format * Use the new script in prepare*.sh * Update deb version getting * Actual use DEB output format for debs * Remove hack from lp-recipe-update-build * Add help string to cli option --- checkbox-core-snap/prepare.sh | 2 +- checkbox-snap/prepare_classic.sh | 2 +- checkbox-snap/prepare_uc.sh | 2 +- tools/release/deb_daily_builds.py | 6 ++- tools/release/get_version.py | 53 ++++++++++++++++++++----- tools/release/lp-recipe-update-build.py | 4 +- tools/release/test_get_version.py | 42 ++++++++++++++++++-- 7 files changed, 91 insertions(+), 20 deletions(-) diff --git a/checkbox-core-snap/prepare.sh b/checkbox-core-snap/prepare.sh index fb5bd6574..c0701b9b0 100755 --- a/checkbox-core-snap/prepare.sh +++ b/checkbox-core-snap/prepare.sh @@ -52,7 +52,7 @@ if which python3 1>/dev/null && which git 1>/dev/null; then # get_version.py produces a version number from the traceability # markers in the history of the repository in the form # vX.Y.Z-devXX, where XX is the number of commits since the latest tag - (cd .. && python3 tools/release/get_version.py -v --dev-suffix) 1>$series/version.txt + (cd .. && python3 tools/release/get_version.py -v --dev-suffix --output-format snap) 1>$series/version.txt else echo "Error: python3 and git binaries are required." echo "Please install them and try again." diff --git a/checkbox-snap/prepare_classic.sh b/checkbox-snap/prepare_classic.sh index 7d6593652..acef23426 100755 --- a/checkbox-snap/prepare_classic.sh +++ b/checkbox-snap/prepare_classic.sh @@ -46,7 +46,7 @@ if which python3 1>/dev/null && which git 1>/dev/null; then # get_version.py produces a version number from the traceability # markers in the history of the repository in the form # vX.Y.Z-devXX, where XX is the number of commits since the latest tag - (cd .. && python3 tools/release/get_version.py -v --dev-suffix) 1>$series/version.txt + (cd .. && python3 tools/release/get_version.py -v --dev-suffix --output-format snap) 1>$series/version.txt else echo "Error: python3 and git binaries are required." echo "Please install them and try again." diff --git a/checkbox-snap/prepare_uc.sh b/checkbox-snap/prepare_uc.sh index 2756091b7..327c2ea8c 100755 --- a/checkbox-snap/prepare_uc.sh +++ b/checkbox-snap/prepare_uc.sh @@ -46,7 +46,7 @@ if which python3 1>/dev/null && which git 1>/dev/null; then # get_version.py produces a version number from the traceability # markers in the history of the repository in the form # vX.Y.Z-devXX, where XX is the number of commits since the latest tag - (cd .. && python3 tools/release/get_version.py -v --dev-suffix) 1>$series/version.txt + (cd .. && python3 tools/release/get_version.py -v --dev-suffix --output-format snap) 1>$series/version.txt else echo "Error: python3 and git binaries are required." echo "Please install them and try again." diff --git a/tools/release/deb_daily_builds.py b/tools/release/deb_daily_builds.py index 16d814b31..f3a6660e5 100755 --- a/tools/release/deb_daily_builds.py +++ b/tools/release/deb_daily_builds.py @@ -24,7 +24,7 @@ from functools import partial from contextlib import suppress -from get_version import get_version +from get_version import get_version, OutputFormats CONFIG_PPA_DEV_TOOLS = """{{ 'wait_max_age_hours' : 10, @@ -97,7 +97,9 @@ def main(): to_check = [] # Find projects new commits from the last 24 hours for name, path in sorted(projects.items(), key=lambda i: i[1]): - version = get_version(dev_suffix=True, verbose=True) + version = get_version( + dev_suffix=True, output_format=OutputFormats.DEB, verbose=True + ) output = ( run( "./tools/release/lp-recipe-update-build.py checkbox " diff --git a/tools/release/get_version.py b/tools/release/get_version.py index ed6736471..a56977f44 100755 --- a/tools/release/get_version.py +++ b/tools/release/get_version.py @@ -42,6 +42,15 @@ logger = logging.getLogger(__name__) +class OutputFormats(Enum): + DEB = "deb" # M.m.p~devXX + TAG = "tag" # vM.m.p-devXX + SNAP = "snap" # M.m.p-devXX + + def __str__(self): + return self.value + + class TraceabilityEnum(Enum): BREAKING = "breaking" NEW = "new" @@ -64,7 +73,7 @@ def describe(self) -> str: description = "patch" return description - def __lt__(self, trace_other: 'Self') -> bool: + def __lt__(self, trace_other: "Self") -> bool: severity = [ TraceabilityEnum.INFRA, TraceabilityEnum.BUGFIX, @@ -159,14 +168,21 @@ def get_needed_bump(history: list[str]) -> TraceabilityEnum: return needed_bump -def add_dev_suffix(version: str, history_len: int): +def add_dev_suffix( + version: str, history_len: int, output_format: OutputFormats +): """ Adds the dev suffix to a version string """ - return f"{version}-dev{history_len}" + dev_prefix = "-" + if output_format == OutputFormats.DEB: + dev_prefix = "~" + return f"{version}{dev_prefix}dev{history_len}" -def bump_version(version: str, needed_bump: TraceabilityEnum) -> str: +def bump_version( + version: str, needed_bump: TraceabilityEnum, output_format: OutputFormats +) -> str: """ Increases to the correct version part given the traceability """ @@ -186,7 +202,11 @@ def bump_version(version: str, needed_bump: TraceabilityEnum) -> str: pass case _: raise ValueError(f"Unknown traceability marker {needed_bump}") - return f"v{major}.{minor}.{patch}" + + prefix = "" + if output_format == OutputFormats.TAG: + prefix = "v" + return f"{prefix}{major}.{minor}.{patch}" def setup_logger(verbose: bool): @@ -214,6 +234,14 @@ def get_cli_args(argv): "of commits since the latest tag" ), ) + parser.add_argument( + "--output-format", + choices=list(OutputFormats), + type=OutputFormats, + default=OutputFormats.TAG, + help="formats the output into a valid version string for the given " + "choice. (default: %(default)s)" + ) parser.add_argument( "repo_path", nargs="?", help="location of the repo (default: cwd)" ) @@ -221,7 +249,10 @@ def get_cli_args(argv): def get_version( - dev_suffix: bool, verbose: bool = False, repo_path: str = None + dev_suffix: bool, + output_format: OutputFormats, + verbose: bool = False, + repo_path: str = None, ) -> str: """ Gets the next version string after calculting the current using tags. @@ -238,10 +269,12 @@ def get_version( raise SystemExit("Could not detect any release worthy commit!") final_version = bumped_version = bump_version( - last_stable_release, needed_bump + last_stable_release, needed_bump, output_format ) if dev_suffix: - final_version = add_dev_suffix(bumped_version, len(history)) + final_version = add_dev_suffix( + bumped_version, len(history), output_format + ) bump_reason = needed_bump.describe() logger.info(f"Detected necessary bump: {bump_reason}") @@ -252,7 +285,9 @@ def get_version( def main(argv): args = get_cli_args(argv) - version = get_version(args.dev_suffix, args.v, args.repo_path) + version = get_version( + args.dev_suffix, args.output_format, args.v, args.repo_path + ) print(version) diff --git a/tools/release/lp-recipe-update-build.py b/tools/release/lp-recipe-update-build.py index 49076f196..c2c297097 100755 --- a/tools/release/lp-recipe-update-build.py +++ b/tools/release/lp-recipe-update-build.py @@ -86,9 +86,7 @@ def main(): ) ) - # pre-release versions (for us, not tagged daily versions) on LP are denoted - # with ~dev[...] not -dev[...] as setuptools_scm marks them - new_version = args.new_version.replace("-dev", "~dev") + new_version = args.new_version text = build_recipe.recipe_text # 0.28.0rc1 → 0.28.0~rc1 diff --git a/tools/release/test_get_version.py b/tools/release/test_get_version.py index a88f7788a..76637708a 100644 --- a/tools/release/test_get_version.py +++ b/tools/release/test_get_version.py @@ -71,9 +71,17 @@ def test_get_needed_bump_warning(self): self.assertEqual(get_version.logger.warning.call_count, 3) self.assertEqual(needed_bump, TraceabilityEnum.INFRA) - def test_add_dev_suffix(self): - postfixed_version = get_version.add_dev_suffix("vX.Y.Z", 24) - self.assertEqual(postfixed_version, "vX.Y.Z-dev24") + def test_add_dev_suffix_snap(self): + postfixed_version = get_version.add_dev_suffix( + "X.Y.Z", 24, get_version.OutputFormats.SNAP + ) + self.assertEqual(postfixed_version, "X.Y.Z-dev24") + + def test_add_dev_suffix_deb(self): + postfixed_version = get_version.add_dev_suffix( + "X.Y.Z", 24, get_version.OutputFormats.DEB + ) + self.assertEqual(postfixed_version, "X.Y.Z~dev24") def test_describe_bump(self): # describe supports all traceability enums @@ -126,6 +134,34 @@ def test_get_version_patch(self, print_mock, check_output_mock): # we didnt ask the dev suffix, so it shouldnt be there self.assertEqual(print_mock.call_args, call("v1.2.4")) + @patch("get_version.check_output") + @patch("get_version.print") + def test_get_version_deb(self, print_mock, check_output_mock): + check_output_mock.side_effect = [ + "v1.2.3", + "a (bugfix) #1\nb (infra) #2\nc (infra) #3", + ] + get_version.main(["--dev-suffix", "--output-format", "deb"]) + self.assertEqual(print_mock.call_count, 1) + # last version is v1.2.3 + # we had at least 1 bugfix, we should get v1.2.4 + # deb version should not start with v and should have a ~ before dev + self.assertEqual(print_mock.call_args, call("1.2.4~dev3")) + + @patch("get_version.check_output") + @patch("get_version.print") + def test_get_version_snap(self, print_mock, check_output_mock): + check_output_mock.side_effect = [ + "v1.2.3", + "a (bugfix) #1\nb (infra) #2\nc (infra) #3", + ] + get_version.main(["--dev-suffix", "--output-format", "snap"]) + self.assertEqual(print_mock.call_count, 1) + # last version is v1.2.3 + # we had at least 1 bugfix, we should get v1.2.4 + # snap version should not start with v and should have a - before dev + self.assertEqual(print_mock.call_args, call("1.2.4-dev3")) + @patch("get_version.check_output") @patch("get_version.print") def test_get_version_error(self, print_mock, check_output_mock):