From 4ef89a4ae29d62630f4d74d779a24d8c3110f666 Mon Sep 17 00:00:00 2001 From: Mike McLean Date: Jun 26 2019 11:36:32 +0000 Subject: PR#1462: rebuildSRPM task Merges #1462 https://pagure.io/koji/pull-request/1462 Fixes: #1396 https://pagure.io/koji/issue/1396 RFE: rebuild srpms before building --- diff --git a/builder/kojid b/builder/kojid index d4504eb..0024e4f 100755 --- a/builder/kojid +++ b/builder/kojid @@ -554,6 +554,39 @@ class BuildRoot(object): msg = '; see %s for more information' % logfile return parseStatus(rv, 'mock') + msg + def rebuild_srpm(self, srpm): + self.session.host.setBuildRootState(self.id,'BUILDING') + + # unpack SRPM to tempdir + srpm_dir = os.path.join(self.tmpdir(), 'srpm_unpacked') + koji.ensuredir(srpm_dir) + top_dir = self.path_without_to_within(srpm_dir) + args = ['--no-clean', '--target', 'noarch', '--chroot', '--', + 'rpm', '--define', '_topdir %s' % top_dir, '-iv', srpm] + rv = self.mock(args) + + # find specfile + spec_files = glob.glob("%s/SPECS/*.spec" % srpm_dir) + if len(spec_files) == 0: + raise koji.BuildError("No spec file found") + elif len(spec_files) > 1: + raise koji.BuildError("Multiple spec files found: %s" % spec_files) + spec_file = os.path.join(top_dir, "SPECS", os.path.basename(spec_files[0])) + + # rebuild SRPM from spec + sources + args = ['--no-clean', '--target', 'noarch', '--chroot', '--', + 'rpmbuild', '--define', '_topdir %s' % top_dir, '-bs', '--nodeps', spec_file] + rv = self.mock(args) + + result_dir = os.path.join(srpm_dir, 'SRPMS') + for fn in glob.glob('%s/*.src.rpm' % result_dir): + shutil.move(os.path.join(result_dir, fn), self.resultdir()) + + if rv: + self.expire() + raise koji.BuildError("error building srpm, %s" % self._mockResult(rv)) + + def build_srpm(self, specfile, sourcedir, source_cmd): self.session.host.setBuildRootState(self.id,'BUILDING') if source_cmd: @@ -1025,12 +1058,31 @@ class BuildTask(BaseTaskHandler): if SCM.is_scm_url(src): return self.getSRPMFromSCM(src, build_tag, repo_id) else: - #assume this is a path under uploads - return src + buildconfig = self.session.getBuildConfig(build_tag, event=self.event_id) + if buildconfig['extra'].get('rebuild_srpm', True): + # default is to always rebuild + return self.getSRPMFromSRPM(src, build_tag, repo_id) + else: + return src else: raise koji.BuildError('Invalid source specification: %s' % src) #XXX - other methods? + def getSRPMFromSRPM(self, src, build_tag, repo_id): + # rebuild srpm in mock, so it gets correct disttag, rpm version, etc. + task_id = self.session.host.subtask(method='rebuildSRPM', + arglist=[src, build_tag, {'repo_id': repo_id, 'scratch': self.opts.get('scratch')}], + label='srpm', + parent=self.id) + # wait for subtask to finish + result = self.wait(task_id)[task_id] + if 'source' in result: + self.source = result['source'] + else: + self.logger.warning('subtask did not provide source data') + srpm = result['srpm'] + return srpm + def getSRPMFromSCM(self, url, build_tag, repo_id): #TODO - allow different ways to get the srpm task_id = self.session.host.subtask(method='buildSRPMFromSCM', @@ -4582,6 +4634,88 @@ class BuildIndirectionImageTask(OzImageTask): return report +class RebuildSRPM(BaseBuildTask): + + Methods = ['rebuildSRPM'] + _taskWeight = 1.0 + + def checkHost(self, hostdata): + tag = self.params[1] + return self.checkHostArch(tag, hostdata) + + def handler(self, srpm, build_tag, opts=None): + if opts is None: + opts = {} + repo_id = opts.get('repo_id') + if not repo_id: + raise koji.BuildError("A repo id must be provided") + + repo_info = self.session.repoInfo(repo_id, strict=True) + event_id = repo_info['create_event'] + build_tag = self.session.getTag(build_tag, strict=True, event=event_id) + + rootopts = {'install_group': 'srpm-build', 'repo_id': repo_id} + br_arch = self.find_arch('noarch', self.session.host.getHost(), self.session.getBuildConfig(build_tag['id'], event=event_id)) + broot = BuildRoot(self.session, self.options, build_tag['id'], br_arch, self.id, **rootopts) + broot.workdir = self.workdir + + self.logger.debug("Initializing buildroot") + broot.init() + + # Setup files and directories for SRPM rebuild + # We can't put this under the mock homedir because that directory + # is completely blown away and recreated on every mock invocation + srpmdir = broot.tmpdir() + '/srpm' + koji.ensuredir(srpmdir) + uploadpath = self.getUploadDir() + + fn = self.localPath("work/%s" % srpm) + if not os.path.exists(fn): + raise koji.BuildError("Input SRPM file missing: %s" % fn) + shutil.copy(fn, srpmdir) + + # rebuild srpm + self.logger.debug("Running srpm rebuild") + br_srpm_path = os.path.join(broot.path_without_to_within(srpmdir), os.path.basename(srpm)) + broot.rebuild_srpm(br_srpm_path) + + srpms = glob.glob('%s/*.src.rpm' % broot.resultdir()) + if len(srpms) == 0: + raise koji.BuildError("No srpms found in %s" % srpmdir) + elif len(srpms) > 1: + raise koji.BuildError("Multiple srpms found in %s: %s" % (srpmdir, ", ".join(srpms))) + else: + srpm = srpms[0] + + # check srpm name + h = koji.get_rpm_header(srpm) + name = koji.get_header_field(h, 'name') + version = koji.get_header_field(h, 'version') + release = koji.get_header_field(h, 'release') + srpm_name = "%(name)s-%(version)s-%(release)s.src.rpm" % locals() + if srpm_name != os.path.basename(srpm): + raise koji.BuildError('srpm name mismatch: %s != %s' % (srpm_name, os.path.basename(srpm))) + + # upload srpm and return + self.uploadFile(srpm) + + brootid = broot.id + log_files = glob.glob('%s/*.log' % broot.resultdir()) + + broot.expire() + + return { + 'srpm': "%s/%s" % (uploadpath, srpm_name), + 'logs': ["%s/%s" % (uploadpath, os.path.basename(f)) + for f in log_files], + 'brootid': brootid, + 'source': { + 'source': os.path.basename(srpm), + 'url': os.path.basename(srpm), + } + } + + class BuildSRPMFromSCMTask(BaseBuildTask): Methods = ['buildSRPMFromSCM'] diff --git a/koji/tasks.py b/koji/tasks.py index 90656b8..6ed02b6 100644 --- a/koji/tasks.py +++ b/koji/tasks.py @@ -172,6 +172,9 @@ LEGACY_SIGNATURES = { 'buildSRPMFromSCM' : [ [['url', 'build_tag', 'opts'], None, None, (None,)], ], + 'rebuildSRPM' : [ + [['srpm', 'build_tag', 'opts'], None, None, (None,)], + ], 'createrepo' : [ [['repo_id', 'arch', 'oldrepo'], None, None, None], ], diff --git a/www/kojiweb/index.py b/www/kojiweb/index.py index a57fa3a..ea09504 100644 --- a/www/kojiweb/index.py +++ b/www/kojiweb/index.py @@ -430,6 +430,7 @@ def notificationdelete(environ, notificationID): # All Tasks _TASKS = ['build', 'buildSRPMFromSCM', + 'rebuildSRPM', 'buildArch', 'chainbuild', 'maven',