From c940e6b1d600ea4f40034cb6d8db4ce44cf335fc Mon Sep 17 00:00:00 2001 From: Otto Urpelainen Date: Oct 31 2021 12:57:07 +0000 Subject: [PATCH 1/2] Add unit test for buildLabel --- diff --git a/tests/test_lib/test_build_label.py b/tests/test_lib/test_build_label.py new file mode 100644 index 0000000..f835af3 --- /dev/null +++ b/tests/test_lib/test_build_label.py @@ -0,0 +1,72 @@ +from __future__ import absolute_import +import mock +import os +import rpm +import unittest + +import koji + +class TestBuildLabel(unittest.TestCase): + def test_buildLabel(self): + """Test the buildLabel method""" + + self.assertRaises(AttributeError, koji.buildLabel, None) + self.assertRaises(AttributeError, koji.buildLabel, 1) + self.assertRaises(AttributeError, koji.buildLabel, []) + + input = {} + ret = koji.buildLabel(input) + self.assertEqual(ret, "None-None-None") + + input = {"name": "foo"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "foo-None-None") + + input = {"version": "1.0.2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "None-1.0.2-None") + + input = {"release": "2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "None-None-2") + + input = {"name": "foo", "version": "1.0.2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "foo-1.0.2-None") + + input = {"name": "foo", "release": "2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "foo-None-2") + + input = {"version": "1.0.2", "release": "2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "None-1.0.2-2") + + input = {"name": "foo", "version": "1.0.2", "release": "2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "foo-1.0.2-2") + + input = {"package_name": "bar", "version": "1.0.2", "release": "2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "bar-1.0.2-2") + + input = { + "package_name": "bar", + "name": "foo", + "version": "1.0.2", + "release": "2" + } + ret = koji.buildLabel(input) + self.assertEqual(ret, "bar-1.0.2-2") + + input = {"epoch": 7, "name": "foo", "version": "1.0.2", "release": "2"} + ret = koji.buildLabel(input) + self.assertEqual(ret, "foo-1.0.2-2") + + input = {"epoch": 7, "name": "foo", "version": "1.0.2", "release": "2"} + ret = koji.buildLabel(input, True) + self.assertEqual(ret, "7:foo-1.0.2-2") + + input = {"name": "foo", "version": "1.0.2", "release": "2"} + ret = koji.buildLabel(input, True) + self.assertEqual(ret, "foo-1.0.2-2") From a42eac659b3457121258836f648308e30315bb35 Mon Sep 17 00:00:00 2001 From: Otto Urpelainen Date: Nov 05 2021 19:06:53 +0000 Subject: [PATCH 2/2] Add utility function to watch builds External tools that interact with Koji need to wait for builds to appear in a repo. For example, Fedora cli tools 'bodhi' and 'fedpkg' can create buildroot overrides, which only become useful after the override's build appears in the correct repo. At the moment, 'bodhi' waits for a repo by invoking the 'koji wait-repo' cli tool while 'fedpkg' does not wait at all. In order to make it easier for such tools to wait for a repo, the wait implementation from 'koji wait-repo' is moved to koji_cli.lib namespace where it is available for use through Python import. --- diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py index 3f8f84c..ea717d5 100644 --- a/cli/koji_cli/commands.py +++ b/cli/koji_cli/commands.py @@ -44,6 +44,7 @@ from koji_cli.lib import ( print_task_recurse, unique_path, warn, + watch_builds, watch_logs, watch_tasks, truncate_string @@ -7339,8 +7340,6 @@ def anon_handle_wait_repo(options, session, args): "value only") (suboptions, args) = parser.parse_args(args) - start = time.time() - builds = [koji.parse_NVR(build) for build in suboptions.builds] if len(args) < 1: parser.error("Please specify a tag name") @@ -7382,38 +7381,12 @@ def anon_handle_wait_repo(options, session, args): warn("nvr %s is not current in tag %s\n latest build in %s is %s" % (expected_nvr, tag, tag, present_nvr)) - last_repo = None - repo = session.getRepo(tag_id) - - while True: - if builds and repo and repo != last_repo: - if koji.util.checkForBuilds(session, tag_id, builds, repo['create_event'], - latest=True): - if not suboptions.quiet: - print("Successfully waited %s for %s to appear in the %s repo" % - (koji.util.duration(start), koji.util.printList(suboptions.builds), tag)) - return - - if (time.time() - start) >= (suboptions.timeout * 60.0): - if not suboptions.quiet: - if builds: - error("Unsuccessfully waited %s for %s to appear in the %s repo" % - (koji.util.duration(start), koji.util.printList(suboptions.builds), tag)) - else: - error("Unsuccessfully waited %s for a new %s repo" % - (koji.util.duration(start), tag)) - error() - - time.sleep(options.poll_interval) - last_repo = repo - repo = session.getRepo(tag_id) - - if not builds: - if repo != last_repo: - if not suboptions.quiet: - print("Successfully waited %s for a new %s repo" % - (koji.util.duration(start), tag)) - return + try: + watch_builds( + session, tag_id, builds, quiet=suboptions.quiet, + poll_interval=options.poll_interval, timeout=suboptions.timeout) + except koji.GenericError as e: + error(str(e)) def handle_regen_repo(options, session, args): diff --git a/cli/koji_cli/lib.py b/cli/koji_cli/lib.py index 90a0a2a..3de987a 100644 --- a/cli/koji_cli/lib.py +++ b/cli/koji_cli/lib.py @@ -819,6 +819,63 @@ def _list_tasks(options, session): return tasklist +def watch_builds(session, tag_id, builds, quiet=False, poll_interval=5, timeout=120): + """Watch for given builds to appear in given tag. If no build are given, + watch for new repo for given tag. + + :param session: Koji session object + :param tag_id: Tag id + :param builds: List of builds as NVR dicts + :param quiet: no/verbose + :param poll_interval: Poll interval in seconds + :param timeout: Watch timeout in minutes""" + last_repo = None + repo = session.getRepo(tag_id) + + # String representations for logs and exceptions + builds_str = koji.util.printList( + [koji.buildLabel(build) for build in builds]) + tag_info = session.getTag(tag_id) + if not tag_info: + raise koji.GenericError("No tag with id: %s" % tag_id) + tag_name = tag_info['name'] + + start = time.time() + while True: + if builds and repo and repo != last_repo: + if koji.util.checkForBuilds(session, tag_id, builds, + repo['create_event'], latest=True): + if not quiet: + print("Successfully waited %s for %s " + "to appear in the %s repo" % + (koji.util.duration(start), builds_str, tag_name)) + return + + if (time.time() - start >= timeout * 60.0): + if not quiet: + if builds: + raise koji.GenericError( + "Unsuccessfully waited %s for %s " + "to appear in the %s repo" % + (koji.util.duration(start), builds_str, tag_name)) + else: + raise koji.GenericError( + "Unsuccessfully waited %s for a new %s repo" % + (koji.util.duration(start), tag_name)) + raise koji.GenericError() + + time.sleep(poll_interval) + last_repo = repo + repo = session.getRepo(tag_id) + + if not builds: + if repo != last_repo: + if not quiet: + print("Successfully waited %s for a new %s repo" % + (koji.util.duration(start), tag_name)) + return + + def format_inheritance_flags(parent): """Return a human readable string of inheritance flags""" flags = ''