diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py index 5da17703..c5bd2852 100644 --- a/cli/koji_cli/commands.py +++ b/cli/koji_cli/commands.py @@ -8161,3 +8161,29 @@ def handle_scheduler_logs(goptions, session, args): for log in logs: print(mask % log) + + +def handle_promote_build(goptions, session, args): + "[misc] Promote a draft build" + usage = "usage: %prog promote-build [options] " + parser = OptionParser(usage=get_usage_str(usage)) + parser.add_option('-f', '--force', action='store_true', default=False, + help='force operation') + (options, args) = parser.parse_args(args) + if len(args) != 1: + parser.error("Please specify a draft build") + draft_build = args[0] + try: + draft_build = int(draft_build) + except ValueError: + pass + activate_session(session, goptions) + if options.force and not session.hasPerm('admin'): + parser.error("--force requires admin privilege") + binfo = session.getBuild(draft_build) + if not binfo: + error("No such build: %s" % draft_build) + if not binfo.get('draft'): + error("Not a draft build: %s" % draft_build) + rinfo = session.promoteBuild(binfo['id'], force=options.force) + print("%s has been promoted to %s" % (binfo['nvr'], rinfo['nvr'])) diff --git a/tests/test_cli/data/list-commands.txt b/tests/test_cli/data/list-commands.txt index ed8a6567..e0799ebb 100644 --- a/tests/test_cli/data/list-commands.txt +++ b/tests/test_cli/data/list-commands.txt @@ -128,6 +128,7 @@ miscellaneous commands: dist-repo Create a yum repo with distribution options import-comps Import group/package information from a comps file moshimoshi Introduce yourself + promote-build Promote a draft build version Report client and hub versions monitor commands: diff --git a/tests/test_cli/test_promote_build.py b/tests/test_cli/test_promote_build.py new file mode 100644 index 00000000..49530aa8 --- /dev/null +++ b/tests/test_cli/test_promote_build.py @@ -0,0 +1,103 @@ +from __future__ import absolute_import +import koji +import locale +import mock +import os +import time +from six.moves import StringIO + +from koji_cli.commands import handle_promote_build +from . import utils + + +class TestPromoteBuild(utils.CliTestCase): + def setUp(self): + self.maxDiff = None + self.options = mock.MagicMock() + self.session = mock.MagicMock() + self.buildinfo = {'id': 1, + 'name': 'foo-bar', + 'nvr': 'foo-bar-1.1-11', + 'package_id': 2, + 'package_name': 'test-rpm', + 'release': '11#draft_1', + 'version': '1.1', + 'draft': True} + self.target_binfo = self.buildinfo.copy() + self.target_binfo['relesae'] = '11' + self.target_binfo['draft'] = False + self.error_format = """Usage: %s promote-build [options] +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) + + @mock.patch('sys.stdout', new_callable=StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_promote_build_valid(self, activate_session, stdout): + build_nvr = 'foo-bar-1.1-11' + self.session.getBuild.return_value = self.buildinfo + self.session.promoteBuild.return_value = self.target_binfo + expected_output = "foo-bar-1.1-11 has been promoted to foo-bar-1.1-11\n" + handle_promote_build(self.options, self.session, [build_nvr]) + self.assert_console_message(stdout, expected_output) + activate_session.assert_called_once_with(self.session, self.options) + self.session.getBuild.assert_called_once_with(build_nvr) + self.session.promoteBuild.assert_called_once_with(self.buildinfo['id'], force=False) + + def test_handle_promote_build_non_exist_build(self): + build_nvr = 'foo-bar-1.1-11' + self.session.getBuild.return_value = None + expected = "No such build: %s\n" % build_nvr + self.assert_system_exit( + handle_promote_build, + self.options, self.session, [build_nvr], + stdout='', + stderr=expected, + exit_code=1) + + def test_handle_promote_build_not_draft(self): + build_nvr = 'foo-bar-1.1-11' + self.session.getBuild.return_value = self.target_binfo + expected = "Not a draft build: %s\n" % build_nvr + self.assert_system_exit( + handle_promote_build, + self.options, self.session, [build_nvr], + stdout='', + stderr=expected, + exit_code=1) + + def test_promote_build_force_not_admin(self): + arguments = ['--force', 'build'] + self.session.hasPerm.return_value = False + self.assert_system_exit( + handle_promote_build, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("--force requires admin privilege"), + exit_code=2) + self.session.getBuild.assert_not_called() + self.session.promoteBuild.assert_not_called() + + def test_promote_build_without_option(self): + arguments = [] + self.assert_system_exit( + handle_promote_build, + self.options, self.session, arguments, + stdout='', + stderr=self.format_error_message("Please specify a draft build"), + exit_code=2, + activate_session=None) + self.session.getBuild.assert_not_called() + self.session.promoteBuild.assert_not_called() + + def test_promote_build_help(self): + self.assert_help( + handle_promote_build, + """Usage: %s promote-build [options] +(Specify the --help global option for a list of other help options) + +Options: + -h, --help show this help message and exit + -f, --force force operation +""" % self.progname)