Move things to rpmautospec Python package

This allows us to reuse code, e.g. to get info out of Koji, for both
calculating release tags and generating the changelog.

Signed-off-by: Nils Philippsen <nils@redhat.com>
This commit is contained in:
Nils Philippsen 2020-02-21 16:50:00 +01:00
parent 6803b2b8c7
commit 3b5dc34a5d
7 changed files with 89 additions and 31 deletions

6
rpmautospec.py Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env python
from rpmautospec.cli import main
main()

0
rpmautospec/__init__.py Normal file
View file

View file

@ -13,6 +13,18 @@ import pygit2
_log = logging.getLogger(__name__) _log = logging.getLogger(__name__)
def register_subcommand(subparsers):
subcmd_name = "generate-changelog"
gen_changelog_parser = subparsers.add_parser(
subcmd_name, help="Generate changelog entries from git commit logs",
)
gen_changelog_parser.add_argument("worktree_path", help="Path to the dist-git worktree")
return subcmd_name
def run_command(command, cwd=None): def run_command(command, cwd=None):
""" Run the specified command in a specific working directory if one """ Run the specified command in a specific working directory if one
is specified. is specified.
@ -31,8 +43,10 @@ def run_command(command, cwd=None):
def main(args): def main(args):
""" Main method. """ """ Main method. """
repo_obj = pygit2.Repository(args[0]) repopath = args.worktree_path
name = os.path.basename(args[0])
repo_obj = pygit2.Repository(repopath)
name = os.path.basename(repopath)
branch = repo_obj.lookup_branch(repo_obj.head.shorthand) branch = repo_obj.lookup_branch(repo_obj.head.shorthand)
commit = branch.peel(pygit2.Commit) commit = branch.peel(pygit2.Commit)
@ -53,7 +67,7 @@ def main(args):
repo_obj.checkout_tree( repo_obj.checkout_tree(
commit, strategy=pygit2.GIT_CHECKOUT_FORCE | pygit2.GIT_CHECKOUT_RECREATE_MISSING, commit, strategy=pygit2.GIT_CHECKOUT_FORCE | pygit2.GIT_CHECKOUT_RECREATE_MISSING,
) )
if os.path.exists(os.path.join(args[0], f"{name}.spec")): if os.path.exists(os.path.join(repopath, f"{name}.spec")):
try: try:
output = run_command( output = run_command(
[ [
@ -63,7 +77,7 @@ def main(args):
"--specfile", "--specfile",
f"{name}.spec", f"{name}.spec",
], ],
cwd=args[0], cwd=repopath,
) )
except Exception: except Exception:
continue continue
@ -108,7 +122,3 @@ def main(args):
) )
print("- %s" % message) print("- %s" % message)
print() print()
if __name__ == "__main__":
main(sys.argv[1:])

43
rpmautospec/cli.py Normal file
View file

@ -0,0 +1,43 @@
import argparse
import sys
from . import changelog, release
subcmd_modules_by_name = {}
def get_cli_args(args):
global subcmd_modules_by_name
parser = argparse.ArgumentParser(prog="rpmautospec")
# global arguments
parser.add_argument(
"--koji-url",
help="The base URL of the Koji hub",
default="https://koji.fedoraproject.org/kojihub",
)
# parsers for sub-commands
subparsers = parser.add_subparsers(dest="subcommand", required=True)
for subcmd_module in (changelog, release):
subcmd_name = subcmd_module.register_subcommand(subparsers)
if subcmd_name in subcmd_modules_by_name:
raise RuntimeError(f"Sub-command specified more than once: {subcmd_name}.")
subcmd_modules_by_name[subcmd_name] = subcmd_module
return parser.parse_args(args)
def main():
args = get_cli_args(sys.argv[1:])
if args.subcommand:
subcmd_module = subcmd_modules_by_name[args.subcommand]
subcmd_module.main(args)

View file

@ -20,29 +20,27 @@ _disttag_re = re.compile(r"^\.?(?P<distcode>[^\d\.]+)(?P<distver>\d+)")
_evr_re = re.compile(r"^(?:(?P<epoch>\d+):)?(?P<version>[^-:]+)(?:-(?P<release>[^-:]+))?$") _evr_re = re.compile(r"^(?:(?P<epoch>\d+):)?(?P<version>[^-:]+)(?:-(?P<release>[^-:]+))?$")
def get_cli_arguments(args): def register_subcommand(subparsers):
""" Set the CLI argument parser and return the argument parsed. subcmd_name = "calculate-release"
"""
parser = argparse.ArgumentParser(description="Script to determine the next NVR of a build") calc_release_parser = subparsers.add_parser(
parser.add_argument( subcmd_name, help="Calculate the next release tag for a package build",
"--koji-url",
help="The base URL of the Koji hub",
default="https://koji.fedoraproject.org/kojihub",
) )
parser.add_argument(
calc_release_parser.add_argument(
"--algorithm", "--algorithm",
"--algo", "--algo",
help="The algorithm with which to determine the next release", help="The algorithm with which to calculate the next release",
choices=["sequential_builds", "holistic_heuristic"], choices=["sequential_builds", "holistic_heuristic"],
default="sequential_builds", default="sequential_builds",
) )
parser.add_argument("package", help="The name of the package of interest") calc_release_parser.add_argument("package", help="The name of the package of interest")
parser.add_argument("dist", help="The dist-tag of interest") calc_release_parser.add_argument("dist", help="The dist-tag of interest")
parser.add_argument( calc_release_parser.add_argument(
"evr", help="The [epoch:]version[-release] of the package", nargs="?", type=parse_evr, "evr", help="The [epoch:]version[-release] of the package", nargs="?", type=parse_evr,
) )
return parser.parse_args(args) return subcmd_name
def parse_evr(evr_str): def parse_evr(evr_str):
@ -255,7 +253,6 @@ def main_holistic_heuristic_algo(args, client, pkgid):
def main(args): def main(args):
""" Main method. """ """ Main method. """
args = get_cli_arguments(args)
client = koji.ClientSession(args.koji_url) client = koji.ClientSession(args.koji_url)
pkgid = client.getPackageID(args.package) pkgid = client.getPackageID(args.package)
@ -267,7 +264,3 @@ def main(args):
main_sequential_builds_algo(args, client, pkgid) main_sequential_builds_algo(args, client, pkgid)
elif args.algorithm == "holistic_heuristic": elif args.algorithm == "holistic_heuristic":
main_holistic_heuristic_algo(args, client, pkgid) main_holistic_heuristic_algo(args, client, pkgid)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))

View file

@ -5,5 +5,5 @@ exclude = .git,.tox,dist,*egg,build,tools
#ignore = #ignore =
# Configure flake8-import-order # Configure flake8-import-order
application-import-names = generate_changelog,next_build application-import-names = rpmautospec
import-order-style = google import-order-style = google

View file

@ -4,7 +4,7 @@ from unittest import mock
import pytest import pytest
import next_build from rpmautospec import release
__here__ = os.path.dirname(__file__) __here__ = os.path.dirname(__file__)
@ -42,13 +42,19 @@ class TestNextBuild:
) as f: ) as f:
koji_list_builds_output = json.load(f) koji_list_builds_output = json.load(f)
with mock.patch("next_build.koji") as mock_koji: with mock.patch("rpmautospec.release.koji") as mock_koji:
mock_client = mock.MagicMock() mock_client = mock.MagicMock()
mock_koji.ClientSession.return_value = mock_client mock_koji.ClientSession.return_value = mock_client
mock_client.getPackageID.return_value = 1234 mock_client.getPackageID.return_value = 1234
mock_client.listBuilds.return_value = koji_list_builds_output mock_client.listBuilds.return_value = koji_list_builds_output
next_build.main((test_data["package"], test_data["dist"])) main_args = mock.Mock()
main_args.algorithm = "sequential_builds"
main_args.package = test_data["package"]
main_args.dist = test_data["dist"]
main_args.evr = None
release.main(main_args)
mock_client.getPackageID.assert_called_once() mock_client.getPackageID.assert_called_once()
mock_client.listBuilds.assert_called_once() mock_client.listBuilds.assert_called_once()