mirror of
https://gitlab.com/kupfer/kupferbootstrap.git
synced 2025-06-24 09:28:21 -04:00
version: add kbs version check functionality and CLI
This commit is contained in:
parent
c844978b4d
commit
821bde59e9
7 changed files with 190 additions and 0 deletions
2
main.py
2
main.py
|
@ -20,6 +20,7 @@ from net.cli import cmd_net
|
|||
from chroot.cli import cmd_chroot
|
||||
from cache.cli import cmd_cache
|
||||
from image.cli import cmd_image
|
||||
from version.cli import cmd_version
|
||||
|
||||
|
||||
@click.group()
|
||||
|
@ -87,6 +88,7 @@ cli.add_command(cmd_flavours)
|
|||
cli.add_command(cmd_image)
|
||||
cli.add_command(cmd_net)
|
||||
cli.add_command(cmd_packages)
|
||||
cli.add_command(cmd_version)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -10,3 +10,4 @@ requests
|
|||
python-dateutil
|
||||
enlighten
|
||||
PyYAML
|
||||
semver
|
||||
|
|
0
version/__init__.py
Normal file
0
version/__init__.py
Normal file
62
version/cli.py
Normal file
62
version/cli.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
import click
|
||||
import logging
|
||||
|
||||
from constants import REPOS_CONFIG_FILE
|
||||
from distro.repo_config import get_repo_config
|
||||
from .kbs import get_kbs_version, compare_kbs_version, compare_kbs_ci_version
|
||||
|
||||
|
||||
@click.group("version", no_args_is_help=False, invoke_without_command=True)
|
||||
@click.pass_context
|
||||
def cmd_version(ctx: click.Context):
|
||||
"""
|
||||
Print KBS version or check for PKGBUILDs compatibility
|
||||
"""
|
||||
if not ctx.invoked_subcommand:
|
||||
ctx.invoke(cmd_version_show)
|
||||
|
||||
|
||||
@cmd_version.command("show")
|
||||
def cmd_version_show():
|
||||
"""
|
||||
Print the current version and exit (default action)
|
||||
"""
|
||||
version = get_kbs_version()
|
||||
if not version:
|
||||
logging.error(f"Failed to fetch KBS version: {version=}")
|
||||
exit(1)
|
||||
print(version)
|
||||
|
||||
|
||||
@cmd_version.command("check")
|
||||
@click.option("--ci-mode", "--ci", is_flag=True, default=False, help="Compare local version against required Build-CI version")
|
||||
def cmd_version_check(ci_mode: bool = False):
|
||||
"""
|
||||
Compare KBS version against minimum version from PKGBUILDs
|
||||
|
||||
The PKGBUILDs repo contains a repos.yml file that contains a minimum KBS version needed/recommended.
|
||||
|
||||
Returns 0 if the KBS version is >= the minimum version.
|
||||
Returns 1 if the KBS version is smaller than the minimum version.
|
||||
Returns 2 on other failures, e.g. missing files.
|
||||
"""
|
||||
kbs_version = get_kbs_version()
|
||||
if not kbs_version:
|
||||
logging.error("Can't compare KBS version as we failed to fetch it")
|
||||
exit(2)
|
||||
repo_config, file_found = get_repo_config(initialize_pkgbuilds=False)
|
||||
if not file_found:
|
||||
logging.error(f"{REPOS_CONFIG_FILE} not found in PKGBUILDs, can't check KBS version for compatibility")
|
||||
exit(2)
|
||||
res = compare_kbs_version(kbs_version=kbs_version, repo_config=repo_config)
|
||||
if ci_mode:
|
||||
res_ci = compare_kbs_ci_version(kbs_version=kbs_version, repo_config=repo_config)
|
||||
if res_ci is None:
|
||||
exit(2)
|
||||
if res_ci:
|
||||
logging.info("KBS CI version is new enough!")
|
||||
if res is None:
|
||||
exit(2)
|
||||
if res:
|
||||
logging.info(f"{'Success: ' if res_ci else ''}KBS version {kbs_version!r} is new enough for PKGBUILDs!")
|
||||
exit(0 if res and res_ci else 1)
|
12
version/compare.py
Normal file
12
version/compare.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
from enum import IntEnum
|
||||
from semver import Version
|
||||
|
||||
|
||||
class VerComp(IntEnum):
|
||||
RIGHT_NEWER = -1
|
||||
EQUAL = 0
|
||||
RIGHT_OLDER = 1
|
||||
|
||||
|
||||
def semver_compare(a: str, b: str) -> VerComp:
|
||||
return VerComp(Version.parse(a).compare(b))
|
79
version/kbs.py
Normal file
79
version/kbs.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
from typing import Union
|
||||
from utils import git
|
||||
|
||||
from .compare import semver_compare, VerComp
|
||||
from distro.repo_config import ReposConfigFile
|
||||
|
||||
KBS_VERSION: Union[str, None] = None
|
||||
|
||||
KBS_VERSION_MIN_KEY = "kbs_min_version"
|
||||
KBS_VERSION_CI_MIN_KEY = 'kbs_ci_version'
|
||||
|
||||
|
||||
def get_kbs_version(kbs_folder: Union[str, None] = None) -> Union[str, None]:
|
||||
if KBS_VERSION:
|
||||
return KBS_VERSION
|
||||
if not kbs_folder:
|
||||
kbs_folder = os.path.join(os.path.dirname(__file__), "..")
|
||||
try:
|
||||
res = git(
|
||||
['describe', '--tags', '--match', 'v*.*.*'],
|
||||
use_git_dir=True,
|
||||
git_dir=os.path.join(kbs_folder, ".git"),
|
||||
capture_output=True,
|
||||
)
|
||||
if res.returncode:
|
||||
output = res.stderr or res.stdout
|
||||
if output and not isinstance(output, str):
|
||||
output = output.decode().strip()
|
||||
raise Exception(output or f'[Git failed without output. Return Code: {res.returncode}]')
|
||||
return (res.stdout or b'').decode().strip()
|
||||
except Exception as ex:
|
||||
logging.warning(f"Failed to fetch KBS version with git: {ex!s}")
|
||||
return None
|
||||
|
||||
|
||||
def compare_kbs_version_generic(
|
||||
kbs_version: str,
|
||||
minimum_ver: str | None,
|
||||
) -> Union[VerComp, None]:
|
||||
if not minimum_ver:
|
||||
return None
|
||||
try:
|
||||
return semver_compare(minimum_ver.lstrip("v"), kbs_version.lstrip("v"))
|
||||
except Exception as ex:
|
||||
logging.warning(f'Failed to compare KBS version {kbs_version!r} to required minimum version {minimum_ver!r}: {ex!r}')
|
||||
return None
|
||||
|
||||
|
||||
def compare_kbs_version(kbs_version: str, repo_config: ReposConfigFile) -> bool | None:
|
||||
"""Returns True if KBS is new enough for PKGBUILDs"""
|
||||
minimum_ver = repo_config.get(KBS_VERSION_MIN_KEY)
|
||||
kbs_state = compare_kbs_version_generic(kbs_version=kbs_version, minimum_ver=minimum_ver)
|
||||
if not minimum_ver:
|
||||
logging.warning(f"Can't check PKGBUILDs for compatible KBS version as {KBS_VERSION_MIN_KEY!r} "
|
||||
'is empty in PKGBUILDs repos.yml')
|
||||
return None
|
||||
if kbs_state == VerComp.RIGHT_OLDER:
|
||||
logging.warning(f'KBS version {kbs_version!r} is older than {minimum_ver!r} required by PKGBUILDs.\n'
|
||||
'Some functionality may randomly be broken.\nYou have been warned.')
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def compare_kbs_ci_version(kbs_version: str, repo_config: ReposConfigFile) -> bool | None:
|
||||
"""Returns True if KBS is new enough for PKGBUILDs in CI"""
|
||||
minimum_ver = repo_config.get(KBS_VERSION_CI_MIN_KEY)
|
||||
if not minimum_ver:
|
||||
logging.warning("Can't check PKGBUILDs for compatible KBS CI version: "
|
||||
f'Minimum CI KBS version {KBS_VERSION_CI_MIN_KEY!r} is empty in PKGBUILDs repos.yml!')
|
||||
return None
|
||||
kbs_state = compare_kbs_version_generic(kbs_version=kbs_version, minimum_ver=minimum_ver)
|
||||
if kbs_state == VerComp.RIGHT_OLDER:
|
||||
logging.error(f'KBS CI version {kbs_version!r} is older than {minimum_ver!r} required by PKGBUILDs kbs_ci_version!\n'
|
||||
'CI is likely to fail!')
|
||||
return False
|
||||
return True
|
34
version/test_kbs_version.py
Normal file
34
version/test_kbs_version.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
from pytest import mark
|
||||
from typing import Optional
|
||||
|
||||
from .kbs import get_kbs_version, compare_kbs_version_generic
|
||||
from .compare import VerComp
|
||||
|
||||
|
||||
def test_get_kbs_version():
|
||||
ver = get_kbs_version()
|
||||
assert ver
|
||||
assert ver.startswith("v")
|
||||
|
||||
|
||||
@mark.parametrize(
|
||||
"minimum_ver, kbs_ver, expected",
|
||||
[
|
||||
("v0.0.1", "v0.0.1", VerComp.EQUAL),
|
||||
("v0.0.1", "v0.0.2", VerComp.RIGHT_NEWER),
|
||||
("v0.0.1-rc0", "v0.0.1-rc1", VerComp.RIGHT_NEWER),
|
||||
("v0.0.1-rc1", "v0.0.1", VerComp.RIGHT_NEWER),
|
||||
("v0.0.1-rc3", "v0.0.2", VerComp.RIGHT_NEWER),
|
||||
("v0.0.1-rc4", "v0.0.1-rc4-3-g12ab34de", VerComp.RIGHT_NEWER),
|
||||
("v0.0.1-rc4-3", "v0.0.1-rc4-3-g12ab34de", VerComp.RIGHT_NEWER),
|
||||
("v0.0.1", "v0.0.1-rc4-3-g12ab34de", VerComp.RIGHT_OLDER),
|
||||
("v0.0.2", "v0.0.1-rc4-3-g12ab34de", VerComp.RIGHT_OLDER),
|
||||
("v0.0.2", None, None),
|
||||
("v0.0.2", "v0.1.0", VerComp.RIGHT_NEWER),
|
||||
("v0.0.2", "v1.0.0", VerComp.RIGHT_NEWER),
|
||||
("v0.2.2", "v0.1.0", VerComp.RIGHT_OLDER),
|
||||
("v0.2.2", "v1.0.0", VerComp.RIGHT_NEWER),
|
||||
],
|
||||
)
|
||||
def test_kbs_version_compare(minimum_ver: str, kbs_ver: str, expected: Optional[VerComp]):
|
||||
assert compare_kbs_version_generic(kbs_version=kbs_ver, minimum_ver=minimum_ver) == expected
|
Loading…
Add table
Add a link
Reference in a new issue