diff --git a/builder/kojid b/builder/kojid index f2ed5e4e..32acc4ee 100755 --- a/builder/kojid +++ b/builder/kojid @@ -857,7 +857,7 @@ class BuildTask(BaseTaskHandler): #(initBuild raises an exception if there is a conflict) try: self.extra_information = { "src": src, "data": data, "target": target } - srpm,rpms,brmap,logs = self.runBuilds(srpm, build_tag, archlist, repo_info['id'], extra) + srpm,rpms,brmap,logs = self.runBuilds(srpm, build_tag, archlist, repo_info['id']) if opts.get('scratch'): #scratch builds do not get imported @@ -958,7 +958,8 @@ class BuildTask(BaseTaskHandler): raise koji.BuildError, "No matching arches were found" return archdict.keys() - def choose_taskarch(self, arch, srpm, build_tag, extra=None): + + def choose_taskarch(self, arch, srpm, build_tag): """Adjust the arch for buildArch subtask as needed""" if koji.util.multi_fnmatch(arch, self.options.literal_task_arches): return arch @@ -969,38 +970,42 @@ class BuildTask(BaseTaskHandler): # see https://pagure.io/koji/issue/19 h = self.readSRPMHeader(srpm) - buildarchs = h[rpm.RPMTAG_BUILDARCHS] exclusivearch = h[rpm.RPMTAG_EXCLUSIVEARCH] excludearch = h[rpm.RPMTAG_EXCLUDEARCH] - if arch in buildarchs and \ - len(buildarchs) == 1 and \ - not exclusivearch and \ - excludearch and \ - arch not in excludearch: - self.logger.debug('find semi-noarch package') + if exclusivearch or excludearch: + # if one of the tag arches is filtered out, then we can't use a + # noarch task buildconfig = self.session.getBuildConfig(build_tag, event=self.event_id) arches = buildconfig['arches'] - tag_archlist = [koji.canonArch(a) for a in arches.split()] - if extra: - arches = "%s %s" % (arches,extra) - - archlist = [a for a in arches.split() if a not in excludearch] - archlist = [a for a in archlist if koji.canonArch(a) in tag_archlist] + tag_arches = [koji.canonArch(a) for a in arches.split()] + exclusivearch = [koji.canonArch(a) for a in exclusivearch] + excludearch = [koji.canonArch(a) for a in excludearch] + archlist = list(tag_arches) + if exclusivearch: + archlist = [ a for a in archlist if a in exclusivearch ] + if excludearch: + archlist = [ a for a in archlist if a not in excludearch ] if not archlist: - raise koji.BuildError, "No matching arches were found to build this semi-noarch package" + raise koji.BuildError("No valid arches were found. tag %r, " + "exclusive %r, exclude %r" % (tag_arches, + exclusivearch, excludearch)) + if set(archlist) != set(tag_arches): + return random.choice(archlist) else: - self.logger.debug("find architectures to build this semi-noarch: %s" % ', '.join(archlist)) - return random.choice(archlist) - else: - return koji.canonArch(arch) + # noarch is ok + return 'noarch' - def runBuilds(self, srpm, build_tag, archlist, repo_id, extra=None): + # otherwise, noarch is ok + return 'noarch' + + + def runBuilds(self, srpm, build_tag, archlist, repo_id): self.logger.debug("Spawning jobs for arches: %r" % (archlist)) subtasks = {} keep_srpm = True for arch in archlist: - taskarch = self.choose_taskarch(arch, srpm, build_tag, extra) + taskarch = self.choose_taskarch(arch, srpm, build_tag) subtasks[arch] = self.session.host.subtask(method='buildArch', arglist=[srpm, build_tag, arch, keep_srpm, {'repo_id': repo_id}], label=arch, diff --git a/tests/test_builder/test_choose_taskarch.py b/tests/test_builder/test_choose_taskarch.py index 0928507f..2bce61df 100644 --- a/tests/test_builder/test_choose_taskarch.py +++ b/tests/test_builder/test_choose_taskarch.py @@ -53,6 +53,7 @@ class TestChooseTaskarch(unittest.TestCase): self.assertEqual(result, 'noarch') def test_excluded_arch(self): + tag_arches = [koji.canonArch(a) for a in self.getBuildConfig()['arches'].split()] # random choice involved, so we repeat this a few times for i in range(20): self.readSRPMHeader.return_value = FakeHeader( @@ -60,8 +61,46 @@ class TestChooseTaskarch(unittest.TestCase): result = self.handler.choose_taskarch('noarch', 'srpm', 'build_tag') self.assertNotEqual(result, 'noarch') self.assertNotEqual(result, 'ppc64') - assert result in self.getBuildConfig()['arches'].split() + self.assertIn(result, tag_arches) + def test_exclusive_arch(self): + tag_arches = [koji.canonArch(a) for a in self.getBuildConfig()['arches'].split()] + # random choice involved, so we repeat this a few times + for i in range(20): + self.readSRPMHeader.return_value = FakeHeader( + buildarchs=['noarch'], exclusivearch=['noarch', 'armv7hl'], excludearch=[]) + result = self.handler.choose_taskarch('noarch', 'srpm', 'build_tag') + self.assertNotEqual(result, 'noarch') + self.assertEqual(result, koji.canonArch('armv7hl')) + self.assertIn(result, tag_arches) + def test_excluded_irrelevant(self): + tag_arches = [koji.canonArch(a) for a in self.getBuildConfig()['arches'].split()] + self.readSRPMHeader.return_value = FakeHeader( + buildarchs=['noarch'], exclusivearch=[], excludearch=['nosucharch']) + result = self.handler.choose_taskarch('noarch', 'srpm', 'build_tag') + self.assertEqual(result, 'noarch') - + def test_literal_arch(self): + self.options.literal_task_arches = 'ARCH' + tag_arches = [koji.canonArch(a) for a in self.getBuildConfig()['arches'].split()] + result = self.handler.choose_taskarch('ARCH', 'srpm', 'build_tag') + self.assertEqual(result, 'ARCH') + + def test_all_excluded(self): + tag_arches = [koji.canonArch(a) for a in self.getBuildConfig()['arches'].split()] + # random choice involved, so we repeat this a few times + for i in range(20): + self.readSRPMHeader.return_value = FakeHeader( + buildarchs=['noarch'], exclusivearch=[], excludearch=tag_arches) + with self.assertRaises(koji.BuildError): + result = self.handler.choose_taskarch('noarch', 'srpm', 'build_tag') + + def test_too_exclusive(self): + tag_arches = [koji.canonArch(a) for a in self.getBuildConfig()['arches'].split()] + # random choice involved, so we repeat this a few times + for i in range(20): + self.readSRPMHeader.return_value = FakeHeader( + buildarchs=['noarch'], exclusivearch=['missing_arch'], excludearch=[]) + with self.assertRaises(koji.BuildError): + result = self.handler.choose_taskarch('noarch', 'srpm', 'build_tag')