diff --git a/0002-Custom-handler-for-koji-watch_tasks.patch b/0002-Custom-handler-for-koji-watch_tasks.patch new file mode 100644 index 0000000..9e4c2d2 --- /dev/null +++ b/0002-Custom-handler-for-koji-watch_tasks.patch @@ -0,0 +1,121 @@ +From 910ed50456ea41995989d59a5a469799ba8d4e5b Mon Sep 17 00:00:00 2001 +From: Ondrej Nosek +Date: Wed, 15 May 2019 18:53:30 +0200 +Subject: [PATCH] Custom handler for koji watch_tasks + +Output text during rhpkg/fedpkg build process states that there +is a 'watch_task' subcommand. When 'koji_cli' library is imported +in rhpkg/fedpkg tool, it shows that command is named +'rhpkg/fedpkg watch_task' instead of 'brew/koji watch_task'. Custom +handler replaces the internal one inside koji_cli library. +Additional fix in rhpkg is needed after this change is released. + +Relates: rhbz#1570921 +Relates: COMPOSE-2809 + +Signed-off-by: Ondrej Nosek +--- + pyrpkg/cli.py | 6 +++++- + pyrpkg/utils.py | 21 +++++++++++++++++++++ + tests/test_cli.py | 39 ++++++++++++++++++++++----------------- + 3 files changed, 48 insertions(+), 18 deletions(-) + +diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py +index 7b83a44..72be1cf 100644 +--- a/pyrpkg/cli.py ++++ b/pyrpkg/cli.py +@@ -1667,7 +1667,11 @@ see API KEY section of copr-cli(1) man page. + if self.args.dry_run: + self.log.info('DRY-RUN: Watch tasks: %s', task_ids) + else: +- return koji_cli.lib.watch_tasks(self.cmd.kojisession, task_ids) ++ return koji_cli.lib.watch_tasks( ++ self.cmd.kojisession, ++ task_ids, ++ ki_handler=utils.make_koji_watch_tasks_handler(self.cmd.build_client) ++ ) + + def extract_greenwave_url(self): + greenwave_url = None +diff --git a/pyrpkg/utils.py b/pyrpkg/utils.py +index 2268e6f..37a39e2 100644 +--- a/pyrpkg/utils.py ++++ b/pyrpkg/utils.py +@@ -128,3 +128,24 @@ def validate_module_build_optional(optional_arg): + 'The "{0}" optional argument is reserved to built-in arguments'.format(key)) + + return (key, value) ++ ++ ++def make_koji_watch_tasks_handler(progname): ++ def koji_watch_tasks_handler(_, tasks, quiet): ++ """ ++ Displays information about running tasks and says how to watch them. ++ Unlike the default version at koji library it overrides progname ++ to show brew, koji or other build client. ++ """ ++ if not quiet: ++ tlist = ['%s: %s' % (t.str(), t.display_state(t.info)) ++ for t in tasks.values() if not t.is_done()] ++ print("""Tasks still running. You can continue to watch with the '%s watch-task' command. ++Running Tasks: %s""" % (progname, '\n'.join(tlist))) ++ ++ # Save reference of the handler during first time use. ++ # It guarantees that the same object is always returned (it allows unittest to pass). ++ global handler_reference ++ if 'handler_reference' not in globals(): ++ handler_reference = koji_watch_tasks_handler ++ return handler_reference +diff --git a/tests/test_cli.py b/tests/test_cli.py +index 785e103..b3e0718 100644 +--- a/tests/test_cli.py ++++ b/tests/test_cli.py +@@ -3235,23 +3235,28 @@ class TestBuildPackage(FakeKojiCreds, CliTestCase): + mock_build_api = None + + with patch('koji_cli.lib.watch_tasks') as watch_tasks: +- with patch('sys.argv', new=cli_cmd): +- cli = self.new_cli(cfg=config_file) +- if sub_command == 'build': +- mock_build_api = session.build +- cli.build() +- elif sub_command == 'scratch-build': +- mock_build_api = session.build +- cli.scratch_build() +- elif sub_command == 'chain-build': +- mock_build_api = session.chainBuild +- cli.chainbuild() +- +- if '--nowait' in cli_cmd: +- watch_tasks.assert_not_called() +- else: +- watch_tasks.assert_called_once_with( +- session, [mock_build_api.return_value]) ++ with patch('pyrpkg.utils.make_koji_watch_tasks_handler') as mock_ki: ++ with patch('sys.argv', new=cli_cmd): ++ cli = self.new_cli(cfg=config_file) ++ if sub_command == 'build': ++ mock_build_api = session.build ++ cli.build() ++ elif sub_command == 'scratch-build': ++ mock_build_api = session.build ++ cli.scratch_build() ++ elif sub_command == 'chain-build': ++ mock_build_api = session.chainBuild ++ cli.chainbuild() ++ ++ if '--nowait' in cli_cmd: ++ watch_tasks.assert_not_called() ++ else: ++ watch_tasks.assert_called_once_with( ++ session, ++ [mock_build_api.return_value], ++ ki_handler=mock_ki.return_value ++ ) ++ self.assertEqual(mock_ki.call_args, (("koji",),)) + + mock_build_api.assert_called_once() + +-- +2.20.1 + diff --git a/0003-Show-nvr-in-container-build.patch b/0003-Show-nvr-in-container-build.patch new file mode 100644 index 0000000..d7a6bae --- /dev/null +++ b/0003-Show-nvr-in-container-build.patch @@ -0,0 +1,75 @@ +From 7cef29d843fabce5abab317303e9016c91414913 Mon Sep 17 00:00:00 2001 +From: Ondrej Nosek +Date: Fri, 24 May 2019 11:21:34 +0200 +Subject: [PATCH] Show nvr in container-build + +JIRA: COMPOSE-3481 + +Signed-off-by: Ondrej Nosek +--- + pyrpkg/__init__.py | 42 ++++++++++++++++++++++++++++++++++-------- + 1 file changed, 34 insertions(+), 8 deletions(-) + +diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py +index 291b9ac..0348420 100644 +--- a/pyrpkg/__init__.py ++++ b/pyrpkg/__init__.py +@@ -3036,6 +3036,39 @@ class Commands(object): + # Run the command + self._run_command(cmd, shell=True) + ++ def _process_koji_task_result(self, task_id): ++ """ ++ Parse and modify output from brew/koji containing information about ++ task (and eventually builds). ++ ++ :param int task_id: id of the current task ++ :return: record containing information about repositories, builds and nvrs ++ :rtype: dict(str, str) ++ """ ++ koji_result = self.kojisession.getTaskResult(task_id) ++ if not koji_result: ++ raise rpkgError('Unknown task: %s' % task_id) ++ koji_builds = koji_result.get("koji_builds", []) ++ koji_result["koji_builds"] = [] ++ ++ for build_id in koji_builds: ++ try: ++ build_id = int(build_id) ++ except ValueError: ++ raise rpkgError("Can not convert 'build_id' to integer: %s" % build_id) ++ ++ bdata = self.kojisession.getBuild(build_id) ++ if not bdata: ++ raise rpkgError('Unknown build: %s' % build_id) ++ nvr = bdata.get("nvr") ++ if nvr: ++ koji_result.setdefault("nvrs", []).append(nvr) ++ ++ koji_result["koji_builds"].append( ++ "%s/buildinfo?buildID=%d" % (self.kojiweburl, build_id)) ++ ++ return koji_result ++ + def container_build_koji(self, target_override=False, opts={}, + kojiconfig=None, kojiprofile=None, + build_client=None, +@@ -3105,14 +3138,7 @@ class Commands(object): + if not nowait: + rv = koji_task_watcher(self.kojisession, [task_id]) + if rv == 0: +- result = self.kojisession.getTaskResult(task_id) +- try: +- result["koji_builds"] = [ +- "%s/buildinfo?buildID=%s" % (self.kojiweburl, +- build_id) +- for build_id in result.get("koji_builds", [])] +- except TypeError: +- pass ++ result = self._process_koji_task_result(task_id) + log_result(self.log.info, result) + + finally: +-- +2.20.1 + diff --git a/0004-Different-import-offline-command-behavior.patch b/0004-Different-import-offline-command-behavior.patch new file mode 100644 index 0000000..b17da5b --- /dev/null +++ b/0004-Different-import-offline-command-behavior.patch @@ -0,0 +1,123 @@ +From 810b2f7efda65ba369f1bb865f25d351915db1ab Mon Sep 17 00:00:00 2001 +From: Ondrej Nosek +Date: Fri, 24 May 2019 17:43:01 +0200 +Subject: [PATCH] Different import --offline command behavior + +`*pkg import --offline` didn't update 'source' and '.gitignore' files. +Modified incorrect output about uploaded sources. Offline mode now does +everything but uploading sources into lookaside cache. + +JIRA: COMPOSE-3558 +Fixes: #445 +Resolves: rhbz#1175262 + +Signed-off-by: Ondrej Nosek +--- + pyrpkg/__init__.py | 5 +++-- + pyrpkg/cli.py | 15 +++++++++++---- + pyrpkg/lookaside.py | 8 +++++++- + tests/test_cli.py | 2 +- + 4 files changed, 22 insertions(+), 8 deletions(-) + +diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py +index 0348420..1f61082 100644 +--- a/pyrpkg/__init__.py ++++ b/pyrpkg/__init__.py +@@ -2818,7 +2818,7 @@ class Commands(object): + self.log.debug('Cleaning up mock temporary config directory: %s', config_dir) + self._cleanup_tmp_dir(config_dir) + +- def upload(self, files, replace=False): ++ def upload(self, files, replace=False, offline=False): + """Upload source file(s) in the lookaside cache + + Both file `sources` and `.gitignore` will be updated with uploaded +@@ -2827,6 +2827,7 @@ class Commands(object): + :param iterable files: an iterable of files to upload. + :param bool replace: optionally replace the existing tracked sources. + Defaults to `False`. ++ :param bool offline: do all the steps except uploading into lookaside cache + :raises rpkgError: if failed to add a file to file `sources`. + """ + +@@ -2859,7 +2860,7 @@ class Commands(object): + gitignore.add('/%s' % file_basename) + self.lookasidecache.upload( + self.ns_repo_name if self.lookaside_namespaced else self.repo_name, +- f, file_hash) ++ f, file_hash, offline=offline) + + sourcesf.write() + gitignore.write() +diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py +index 72be1cf..eb0f499 100644 +--- a/pyrpkg/cli.py ++++ b/pyrpkg/cli.py +@@ -2027,13 +2027,20 @@ see API KEY section of copr-cli(1) man page. + + def import_srpm(self): + uploadfiles = self.cmd.import_srpm(self.args.srpm) +- if uploadfiles and not self.args.offline: +- self.cmd.upload(uploadfiles, replace=True) ++ if uploadfiles: ++ self.cmd.upload(uploadfiles, replace=True, offline=self.args.offline) + if not self.args.skip_diffs: + self.cmd.diff(cached=True) + self.log.info('--------------------------------------------') +- self.log.info("New content staged and new sources uploaded.") +- self.log.info("Commit if happy or revert with: git reset --hard HEAD") ++ if uploadfiles and self.args.offline: ++ self.log.info("New content staged without uploading sources.") ++ self.log.info("Commit and upload (%s upload ) if happy or revert with: " ++ "'git reset --hard HEAD' (warning: it reverts also eventual user " ++ "changes)." % (self._name,)) ++ else: ++ self.log.info("New content staged and new sources uploaded.") ++ self.log.info("Commit if happy or revert with: 'git reset --hard HEAD' (warning: " ++ "it reverts also eventual user changes).") + + def install(self): + self.sources() +diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py +index d28c1d9..ede81ea 100644 +--- a/pyrpkg/lookaside.py ++++ b/pyrpkg/lookaside.py +@@ -269,7 +269,7 @@ class CGILookasideCache(object): + raise UploadError('Error checking for %s at %s' + % (filename, self.upload_url)) + +- def upload(self, name, filepath, hash): ++ def upload(self, name, filepath, hash, offline=False): + """Upload a source file + + :param str name: The name of the module. (usually the name of the SRPM) +@@ -277,7 +277,13 @@ class CGILookasideCache(object): + server side expects). + :param str filepath: The full path to the file to upload. + :param str hash: The known good hash of the file. ++ :param bool offline: Method prints a message about disabled upload and does return. + """ ++ if offline: ++ self.log.info("Uploading: %s", filepath) ++ self.log.info("*Upload disabled*") ++ return ++ + filename = os.path.basename(filepath) + + # As in remote_file_exists, we need to convert unicode strings to str +diff --git a/tests/test_cli.py b/tests/test_cli.py +index b3e0718..ee92389 100644 +--- a/tests/test_cli.py ++++ b/tests/test_cli.py +@@ -1163,7 +1163,7 @@ class LookasideCacheMock(object): + def destroy_lookaside_cache(self): + shutil.rmtree(self.lookasidecache_storage) + +- def lookasidecache_upload(self, repo_name, filepath, hash): ++ def lookasidecache_upload(self, repo_name, filepath, hash, offline): + filename = os.path.basename(filepath) + storage_filename = os.path.join(self.lookasidecache_storage, filename) + with open(storage_filename, 'wb') as fout: +-- +2.20.1 + diff --git a/rpkg.spec b/rpkg.spec index 5d6180a..8399f93 100644 --- a/rpkg.spec +++ b/rpkg.spec @@ -4,7 +4,7 @@ Name: rpkg Version: 1.58 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Python library for interacting with rpm+git License: GPLv2+ and LGPLv2 @@ -22,6 +22,9 @@ Source0: https://pagure.io/releases/rpkg/%{name}-%{version}.tar.gz # remove rpm-py-installer for now. Patch0: remove-koji-and-rpm-py-installer-from-requires.patch Patch1: 0001-Fix-clone-branches.patch +Patch2: 0002-Custom-handler-for-koji-watch_tasks.patch +Patch3: 0003-Show-nvr-in-container-build.patch +Patch4: 0004-Different-import-offline-command-behavior.patch %if 0%{?fedora} || 0%{?rhel} > 7 # Enable python3 build by default @@ -262,6 +265,11 @@ nosetests tests %changelog +* Mon May 27 2019 Ondřej Nosek - 1.58-3 +- Backport: Custom handler for koji watch_tasks +- Backport: Show nvr in container-build +- Backport: Different import --offline command behavior + * Thu May 09 2019 Ondrej Nosek - 1.58-2 - Backport: fixed 'clone --branch' command