diff --git a/.gitignore b/.gitignore index a3c822c..218a8c9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ koji-1.4.0.tar.bz2 /koji-1.14.0.tar.bz2 /koji-1.15.0.tar.bz2 /koji-1.15.1.tar.bz2 +/koji-1.16.0.tar.bz2 diff --git a/735.patch b/735.patch deleted file mode 100644 index d2c448b..0000000 --- a/735.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 323926afbf4d1337e1bcdfc07e7d8e64f6289bf1 Mon Sep 17 00:00:00 2001 -From: Patrick Uiterwijk -Date: Dec 07 2017 01:55:04 +0000 -Subject: Fix encoding issue in runroot with python3 - - -This will make sure that the log from the server is correctly decoded, since -sys.stdout only accepts strings, not raw bytes, which is what downloadTaskOutput -returns. - -Signed-off-by: Patrick Uiterwijk - ---- - -diff --git a/plugins/cli/runroot.py b/plugins/cli/runroot.py -index f8d4b50..dc5d737 100644 ---- a/plugins/cli/runroot.py -+++ b/plugins/cli/runroot.py -@@ -90,7 +90,7 @@ def handle_runroot(options, session, args): - if 'runroot.log' in output: - for volume in output['runroot.log']: - log = session.downloadTaskOutput(task_id, 'runroot.log', volume=volume) -- sys.stdout.write(log) -+ sys.stdout.write(log.decode('utf8')) - info = session.getTaskInfo(task_id) - if info is None: - sys.exit(1) - diff --git a/794.patch b/794.patch deleted file mode 100644 index 9864e9d..0000000 --- a/794.patch +++ /dev/null @@ -1,354 +0,0 @@ -From b975594ce4ec1df300eccc261bedbd607e2c2aa0 Mon Sep 17 00:00:00 2001 -From: Mike McLean -Date: Feb 01 2018 15:12:52 +0000 -Subject: [PATCH 1/4] recheck for duplicate external rpm on insertion errors - - -fixes: https://pagure.io/koji/issue/788 - ---- - -diff --git a/hub/kojihub.py b/hub/kojihub.py -index 7e664af..4500acd 100644 ---- a/hub/kojihub.py -+++ b/hub/kojihub.py -@@ -5730,7 +5730,7 @@ def add_external_rpm(rpminfo, external_repo, strict=True): - - # [!] Calling function should perform access checks - -- #sanity check rpminfo -+ # sanity check rpminfo - dtypes = ( - ('name', basestring), - ('version', basestring), -@@ -5746,37 +5746,47 @@ def add_external_rpm(rpminfo, external_repo, strict=True): - if not isinstance(rpminfo[field], allowed): - #this will catch unwanted NULLs - raise koji.GenericError("Invalid value for %s: %r" % (field, rpminfo[field])) -- #TODO: more sanity checks for payloadhash -+ # strip extra fields -+ rpminfo = dslice(rpminfo, [x[0] for x in dtypes]) -+ # TODO: more sanity checks for payloadhash - -- #Check to see if we have it -- data = rpminfo.copy() -- data['location'] = external_repo -- previous = get_rpm(data, strict=False) -+ def check_dup(): -+ # Check to see if we have it -+ data = rpminfo.copy() -+ data['location'] = external_repo -+ previous = get_rpm(data, strict=False) -+ if previous: -+ disp = "%(name)s-%(version)s-%(release)s.%(arch)s@%(external_repo_name)s" % previous -+ if strict: -+ raise koji.GenericError("external rpm already exists: %s" % disp) -+ elif data['payloadhash'] != previous['payloadhash']: -+ raise koji.GenericError("hash changed for external rpm: %s (%s -> %s)" \ -+ % (disp, previous['payloadhash'], data['payloadhash'])) -+ else: -+ return previous -+ -+ previous = check_dup() - if previous: -- disp = "%(name)s-%(version)s-%(release)s.%(arch)s@%(external_repo_name)s" % previous -- if strict: -- raise koji.GenericError("external rpm already exists: %s" % disp) -- elif data['payloadhash'] != previous['payloadhash']: -- raise koji.GenericError("hash changed for external rpm: %s (%s -> %s)" \ -- % (disp, previous['payloadhash'], data['payloadhash'])) -- else: -- return previous -+ return previous - -- #add rpminfo entry -- rpminfo['external_repo_id'] = get_external_repo_id(external_repo, strict=True) -- rpminfo['id'] = _singleValue("""SELECT nextval('rpminfo_id_seq')""") -- q = """INSERT INTO rpminfo (id, build_id, buildroot_id, -- name, version, release, epoch, arch, -- external_repo_id, -- payloadhash, size, buildtime) -- VALUES (%(id)i, NULL, NULL, -- %(name)s, %(version)s, %(release)s, %(epoch)s, %(arch)s, -- %(external_repo_id)i, -- %(payloadhash)s, %(size)i, %(buildtime)i) -- """ -- _dml(q, rpminfo) -+ # add rpminfo entry -+ data = rpminfo.copy() -+ data['external_repo_id'] = get_external_repo_id(external_repo, strict=True) -+ data['id'] = nextval('rpminfo_id_seq') -+ data['build_id'] = None -+ data['buildroot_id'] = None -+ insert = InsertProcessor('rpminfo', data=data) -+ try: -+ insert.execute() -+ except Exception: -+ # check for dup again to work around a race -+ # see: https://pagure.io/koji/issue/788 -+ previous = check_dup() -+ if previous: -+ return previous -+ raise - -- return get_rpm(rpminfo['id']) -+ return get_rpm(data['id']) - - def import_build_log(fn, buildinfo, subdir=None): - """Move a logfile related to a build to the right place""" - -From 6dd0cb86ce5aa07d7fb199ea55e35cdec9d3d49d Mon Sep 17 00:00:00 2001 -From: Mike McLean -Date: Feb 04 2018 13:01:27 +0000 -Subject: [PATCH 2/4] use a savepoint - - ---- - -diff --git a/hub/kojihub.py b/hub/kojihub.py -index 4500acd..3da3def 100644 ---- a/hub/kojihub.py -+++ b/hub/kojihub.py -@@ -5776,11 +5776,13 @@ def add_external_rpm(rpminfo, external_repo, strict=True): - data['build_id'] = None - data['buildroot_id'] = None - insert = InsertProcessor('rpminfo', data=data) -+ savepoint = Savepoint('pre_insert') - try: - insert.execute() - except Exception: -- # check for dup again to work around a race -+ # if this failed, it likely duplicates one just inserted - # see: https://pagure.io/koji/issue/788 -+ savepoint.rollback() - previous = check_dup() - if previous: - return previous -@@ -7395,6 +7397,16 @@ def nextval(sequence): - return _singleValue("SELECT nextval(%(sequence)s)", data, strict=True) - - -+class Savepoint(object): -+ -+ def __init__(self, name): -+ self.name = name -+ _dml("SAVEPOINT %s" % name, {}) -+ -+ def rollback(self): -+ _dml("ROLLBACK TO SAVEPOINT %s" % self.name, {}) -+ -+ - def parse_json(value, desc=None, errstr=None): - if value is None: - return value - -From 3c5c9f74d446ee6bca15cadceaf3c21b2f26be7c Mon Sep 17 00:00:00 2001 -From: Mike McLean -Date: Feb 04 2018 15:08:00 +0000 -Subject: [PATCH 3/4] unit test for add_external_rpm - - ---- - -diff --git a/tests/test_hub/test_add_external_rpm.py b/tests/test_hub/test_add_external_rpm.py -new file mode 100644 -index 0000000..7aa928b ---- /dev/null -+++ b/tests/test_hub/test_add_external_rpm.py -@@ -0,0 +1,158 @@ -+import mock -+import unittest -+ -+import koji -+import kojihub -+ -+ -+IP = kojihub.InsertProcessor -+ -+ -+class FakeException(Exception): -+ pass -+ -+ -+class TestAddExternalRPM(unittest.TestCase): -+ -+ def setUp(self): -+ self.get_rpm = mock.patch('kojihub.get_rpm').start() -+ self.get_external_repo_id = mock.patch('kojihub.get_external_repo_id').start() -+ self.nextval = mock.patch('kojihub.nextval').start() -+ self.Savepoint = mock.patch('kojihub.Savepoint').start() -+ self.InsertProcessor = mock.patch('kojihub.InsertProcessor', -+ side_effect=self.getInsert).start() -+ self.inserts = [] -+ self.insert_execute = mock.MagicMock() -+ -+ self.rpminfo = { -+ 'name': 'NAME', -+ 'version': 'VERSION', -+ 'release': 'RELEASE', -+ 'epoch': None, -+ 'arch': 'noarch', -+ 'payloadhash': 'fakehash', -+ 'size': 42, -+ 'buildtime': 0, -+ } -+ self.repo = 'myrepo' -+ -+ def tearDown(self): -+ mock.patch.stopall() -+ -+ def getInsert(self, *args, **kwargs): -+ insert = IP(*args, **kwargs) -+ insert.execute = self.insert_execute -+ self.inserts.append(insert) -+ return insert -+ -+ def test_add_ext_rpm(self): -+ self.get_rpm.return_value = None -+ self.get_external_repo_id.return_value = mock.sentinel.repo_id -+ self.nextval.return_value = mock.sentinel.rpm_id -+ -+ # call it -+ kojihub.add_external_rpm(self.rpminfo, self.repo) -+ -+ self.assertEqual(len(self.inserts), 1) -+ insert = self.inserts[0] -+ self.assertEqual(insert.data['external_repo_id'], mock.sentinel.repo_id) -+ self.assertEqual(insert.data['id'], mock.sentinel.rpm_id) -+ self.assertEqual(insert.table, 'rpminfo') -+ -+ def test_add_ext_rpm_bad_data(self): -+ rpminfo = self.rpminfo.copy() -+ del rpminfo['size'] -+ -+ with self.assertRaises(koji.GenericError): -+ kojihub.add_external_rpm(rpminfo, self.repo) -+ -+ self.get_rpm.assert_not_called() -+ self.nextval.assert_not_called() -+ self.assertEqual(len(self.inserts), 0) -+ -+ rpminfo = self.rpminfo.copy() -+ rpminfo['size'] = ['invalid type'] -+ -+ with self.assertRaises(koji.GenericError): -+ kojihub.add_external_rpm(rpminfo, self.repo) -+ -+ self.get_rpm.assert_not_called() -+ self.nextval.assert_not_called() -+ self.assertEqual(len(self.inserts), 0) -+ -+ def test_add_ext_rpm_dup(self): -+ prev = self.rpminfo.copy() -+ prev['external_repo_id'] = mock.sentinel.repo_id -+ prev['external_repo_name'] = self.repo -+ self.get_rpm.return_value = prev -+ self.get_external_repo_id.return_value = mock.sentinel.repo_id -+ -+ # call it (default is strict) -+ with self.assertRaises(koji.GenericError): -+ kojihub.add_external_rpm(self.rpminfo, self.repo) -+ -+ self.assertEqual(len(self.inserts), 0) -+ self.nextval.assert_not_called() -+ -+ # call it without strict -+ ret = kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False) -+ -+ self.assertEqual(ret, self.get_rpm.return_value) -+ self.assertEqual(len(self.inserts), 0) -+ self.nextval.assert_not_called() -+ -+ # different hash -+ prev['payloadhash'] = 'different hash' -+ with self.assertRaises(koji.GenericError): -+ kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False) -+ -+ self.assertEqual(len(self.inserts), 0) -+ self.nextval.assert_not_called() -+ -+ def test_add_ext_rpm_dup_late(self): -+ prev = self.rpminfo.copy() -+ prev['external_repo_id'] = mock.sentinel.repo_id -+ prev['external_repo_name'] = self.repo -+ self.get_rpm.side_effect = [None, prev] -+ self.get_external_repo_id.return_value = mock.sentinel.repo_id -+ self.insert_execute.side_effect = FakeException('insert failed') -+ -+ # call it (default is strict) -+ with self.assertRaises(koji.GenericError): -+ kojihub.add_external_rpm(self.rpminfo, self.repo) -+ -+ self.assertEqual(len(self.inserts), 1) -+ self.nextval.assert_called_once() -+ -+ # call it without strict -+ self.inserts[:] = [] -+ self.nextval.reset_mock() -+ self.get_rpm.side_effect = [None, prev] -+ ret = kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False) -+ -+ self.assertEqual(ret, prev) -+ self.assertEqual(len(self.inserts), 1) -+ self.nextval.assert_called_once() -+ -+ # different hash -+ self.inserts[:] = [] -+ self.nextval.reset_mock() -+ self.get_rpm.side_effect = [None, prev] -+ prev['payloadhash'] = 'different hash' -+ with self.assertRaises(koji.GenericError): -+ kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False) -+ -+ self.assertEqual(len(self.inserts), 1) -+ self.nextval.assert_called_once() -+ -+ # no dup after failed insert -+ self.inserts[:] = [] -+ self.nextval.reset_mock() -+ self.get_rpm.side_effect = [None, None] -+ with self.assertRaises(FakeException): -+ kojihub.add_external_rpm(self.rpminfo, self.repo, strict=False) -+ -+ self.assertEqual(len(self.inserts), 1) -+ self.nextval.assert_called_once() -+ -+ - -From a7e866cf8a39f56e694372cfd9d6099f7bc5be0d Mon Sep 17 00:00:00 2001 -From: Mike McLean -Date: Feb 04 2018 15:15:40 +0000 -Subject: [PATCH 4/4] unit test for Savepoint - - ---- - -diff --git a/tests/test_hub/test_savepoint.py b/tests/test_hub/test_savepoint.py -new file mode 100644 -index 0000000..279729e ---- /dev/null -+++ b/tests/test_hub/test_savepoint.py -@@ -0,0 +1,22 @@ -+import mock -+import unittest -+ -+import kojihub -+ -+ -+class TestSavepoint(unittest.TestCase): -+ -+ def setUp(self): -+ self.dml = mock.patch('kojihub._dml').start() -+ -+ def tearDown(self): -+ mock.patch.stopall() -+ -+ def test_savepoint(self): -+ sp = kojihub.Savepoint('some_name') -+ self.assertEqual(sp.name, 'some_name') -+ self.dml.assert_called_once_with('SAVEPOINT some_name', {}) -+ -+ self.dml.reset_mock() -+ sp.rollback() -+ self.dml.assert_called_once_with('ROLLBACK TO SAVEPOINT some_name', {}) - diff --git a/841.patch b/841.patch deleted file mode 100644 index a13e2a1..0000000 --- a/841.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff -Nur koji-1.15.0.orig/builder/kojid koji-1.15.0/builder/kojid ---- koji-1.15.0.orig/builder/kojid 2018-03-16 11:56:22.542475550 -0700 -+++ koji-1.15.0/builder/kojid 2018-03-16 11:58:57.281149897 -0700 -@@ -3491,8 +3491,8 @@ - #IF specific - 'imgdir': os.path.join(self.workdir, 'scratch_images'), - 'tmpdir': os.path.join(self.workdir, 'oz-tmp'), -- 'verbose' : True, -- 'timeout': 7200, -+ 'verbose': True, -+ 'timeout': self.options.oz_install_timeout, - 'output': 'log', - 'raw': False, - 'debug': True, -@@ -5652,6 +5652,7 @@ - 'resolver-status.properties *.lastUpdated', - 'failed_buildroot_lifetime' : 3600 * 4, - 'rpmbuild_timeout' : 3600 * 24, -+ 'oz_install_timeout': None, - 'cert': None, - 'ca': '', # FIXME: Unused, remove in next major release - 'serverca': None} -@@ -5659,7 +5660,7 @@ - for name, value in config.items('kojid'): - if name in ['sleeptime', 'maxjobs', 'minspace', 'retry_interval', - 'max_retries', 'offline_retry_interval', 'failed_buildroot_lifetime', -- 'timeout', 'rpmbuild_timeout',]: -+ 'timeout', 'rpmbuild_timeout', 'oz_install_timeout',]: - try: - defaults[name] = int(value) - except ValueError: -diff -Nur koji-1.15.0.orig/builder/kojid.conf koji-1.15.0/builder/kojid.conf ---- koji-1.15.0.orig/builder/kojid.conf 2017-12-18 14:10:22.000000000 -0800 -+++ koji-1.15.0/builder/kojid.conf 2018-03-16 11:59:35.122314808 -0700 -@@ -35,6 +35,10 @@ - ; Timeout for build duration (24 hours) - ; rpmbuild_timeout=86400 - -+; Install timeout(seconds) for image build -+; if it's unset, use the number in /etc/oz/oz.cfg, supported since oz-0.16.0 -+; oz_install_timeout=7200 -+ - ; The URL for the xmlrpc server - server=http://hub.example.com/kojihub - -diff -Nur koji-1.15.0.orig/docs/source/image_build.rst koji-1.15.0/docs/source/image_build.rst ---- koji-1.15.0.orig/docs/source/image_build.rst 2017-12-18 14:10:22.000000000 -0800 -+++ koji-1.15.0/docs/source/image_build.rst 2018-03-16 12:00:26.644539341 -0700 -@@ -660,6 +660,11 @@ - #. python-psphere => 0.5 - #. VMDKStream => 0.2 - #. pykickstart -+#. Edit ``/etc/kojid/kojid.conf``, and set an second value, eg: 7200 for -+ ``oz_install_timeout``. It's a timeout waiting guest installing. If it's -+ not specified, oz will use its default value. Since ``oz-0.16.0`` it can be -+ configured in ``/etc/oz/oz.cfg`` as ``install`` in the ``[timeouts]`` -+ section. - #. Edit ``/etc/oz/oz.cfg``, and set the memory value in the ``[libvirt]`` - section to at least 2048. Set ``safe_generation`` under ``[icicle]`` to yes. - #. Run: ``mkdir -p ~root/.psphere/templates``, and then copy the following diff --git a/koji.spec b/koji.spec index d456d68..e6ab4f5 100644 --- a/koji.spec +++ b/koji.spec @@ -25,8 +25,8 @@ %endif Name: koji -Version: 1.15.1 -Release: 3%{?dist} +Version: 1.16.0 +Release: 1%{?dist} # koji.ssl libs (from plague) are GPLv2+ License: LGPLv2 and GPLv2+ Summary: Build system tools @@ -34,11 +34,6 @@ Group: Applications/System URL: https://pagure.io/koji/ Source0: https://releases.pagure.org/koji/koji-%{version}.tar.bz2 -# Backported patches -Patch0: https://pagure.io/koji/pull-request/735.patch -Patch1: https://pagure.io/koji/pull-request/794.patch -Patch2: https://pagure.io/koji/pull-request/841.patch - # Not upstreamable Patch100: fedora-config.patch @@ -243,9 +238,6 @@ koji-web is a web UI to the Koji system. %prep %setup -q -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 %patch100 -p1 -b .fedoraconfig %build @@ -297,7 +289,6 @@ sed -i 's/\#\!\/usr\/bin\/python/\#\!\/usr\/bin\/python3/' $RPM_BUILD_ROOT/usr/b %files hub %{_datadir}/koji-hub %dir %{_libexecdir}/koji-hub -%{_libexecdir}/koji-hub/rpmdiff %config(noreplace) /etc/httpd/conf.d/kojihub.conf %dir /etc/koji-hub %config(noreplace) /etc/koji-hub/hub.conf @@ -438,6 +429,9 @@ fi %endif %changelog +* Tue Jul 31 2018 Kevin Fenzi - 1.16.0-1 +- Update to 1.16.0 + * Fri Jul 13 2018 Fedora Release Engineering - 1.15.1-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild diff --git a/sources b/sources index dffda0e..d46e6de 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (koji-1.15.1.tar.bz2) = 324e9ce4efed9b51eddbe05e159edf3a419b02e7b9eb60fab312f4662402f68c9743afd65417c759187addd5701b018870a322613be20aeeaf82720426765766 +SHA512 (koji-1.16.0.tar.bz2) = c1a0f8cf76949b597ee6207b74d91b3e70f150155f89953f710256ed898fb8ad4c4d5f347f2b1d8219ddf9e66195fb713e05d345048291f848cd26a406100426