launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #28741
[Merge] ~cjwatson/launchpad:refactor-ci-build-upload-job into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:refactor-ci-build-upload-job into launchpad:master with ~cjwatson/launchpad:ci-build-upload-require-package as a prerequisite.
Commit message:
Refactor CIBuildUploadJob.run
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/426403
The `CIBuildUploadJob.run` method was getting a bit long and unwieldy. Break it up with a couple of new helper methods.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:refactor-ci-build-upload-job into launchpad:master.
diff --git a/lib/lp/soyuz/model/archivejob.py b/lib/lp/soyuz/model/archivejob.py
index e2bf402..ab98138 100644
--- a/lib/lp/soyuz/model/archivejob.py
+++ b/lib/lp/soyuz/model/archivejob.py
@@ -1,6 +1,7 @@
# Copyright 2010-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from collections import OrderedDict
import io
import json
import logging
@@ -202,6 +203,13 @@ class ScanException(Exception):
"""A CI build upload job failed to scan a file."""
+class ScannedArtifact:
+
+ def __init__(self, *, artifact, metadata):
+ self.artifact = artifact
+ self.metadata = metadata
+
+
@implementer(ICIBuildUploadJob)
@provider(ICIBuildUploadJobSource)
class CIBuildUploadJob(ArchiveJobDerived):
@@ -375,26 +383,21 @@ class CIBuildUploadJob(ArchiveJobDerived):
else:
return None
- def run(self):
- """See `IRunnableJob`."""
- build_target = self.ci_build.git_repository.target
- if not IDistributionSourcePackage.providedBy(build_target):
- # This should be caught by `Archive.uploadCIBuild`, but check it
- # here as well just in case.
- logger.warning(
- "Source CI build is for %s, which is not a package",
- repr(build_target))
- return
+ def _scanArtifacts(self, artifacts):
+ """Scan an iterable of `RevisionStatusArtifact`s for metadata.
+
+ Skips log artifacts, artifacts we don't understand, and artifacts
+ not relevant to the target archive's repository format.
+
+ Returns a list of `ScannedArtifact`s containing metadata for
+ relevant artifacts.
+ """
+ allowed_binary_formats = (
+ self.binary_format_by_repository_format.get(
+ self.archive.repository_format, set()))
+ scanned = []
with tempfile.TemporaryDirectory(prefix="ci-build-copy-job") as tmpdir:
- releases = {
- (release.binarypackagename, release.binpackageformat): release
- for release in self.ci_build.binarypackages}
- allowed_binary_formats = (
- self.binary_format_by_repository_format.get(
- self.archive.repository_format, set()))
- binaries = {}
- for artifact in getUtility(
- IRevisionStatusArtifactSet).findByCIBuild(self.ci_build):
+ for artifact in artifacts:
if artifact.artifact_type == RevisionStatusArtifactType.LOG:
continue
name = artifact.library_file.filename
@@ -403,37 +406,65 @@ class CIBuildUploadJob(ArchiveJobDerived):
copy_and_close(artifact.library_file, open(contents, "wb"))
metadata = self._scanFile(contents)
if metadata is None:
- logger.info("No upload handler for %s" % name)
+ logger.info("No upload handler for %s", name)
continue
- binpackageformat = metadata["binpackageformat"]
- if binpackageformat not in allowed_binary_formats:
+ if metadata["binpackageformat"] not in allowed_binary_formats:
logger.info(
- "Skipping %s (not relevant to %s archives)" % (
- name, self.archive.repository_format))
+ "Skipping %s (not relevant to %s archives)",
+ name, self.archive.repository_format)
continue
- logger.info(
- "Uploading %s to %s %s (%s)" % (
- name, self.archive.reference,
- self.target_distroseries.getSuite(self.target_pocket),
- self.target_channel))
- metadata["binarypackagename"] = bpn = (
- getUtility(IBinaryPackageNameSet).ensure(metadata["name"]))
- del metadata["name"]
- filetype = self.filetype_by_format[binpackageformat]
- bpr = releases.get((bpn, binpackageformat))
- if bpr is None:
- bpr = self.ci_build.createBinaryPackageRelease(**metadata)
- for bpf in bpr.files:
- if (bpf.libraryfile == artifact.library_file and
- bpf.filetype == filetype):
- break
- else:
- bpr.addFile(artifact.library_file, filetype=filetype)
- # The publishBinaries interface was designed for .debs,
- # which need extra per-binary "override" information
- # (component, etc.). None of this is relevant here.
- binaries[bpr] = (None, None, None, None)
- if binaries:
- getUtility(IPublishingSet).publishBinaries(
- self.archive, self.target_distroseries, self.target_pocket,
- binaries, channel=self.target_channel)
+ scanned.append(
+ ScannedArtifact(artifact=artifact, metadata=metadata))
+ return scanned
+
+ def _uploadBinaries(self, scanned):
+ """Upload an iterable of `ScannedArtifact`s to an archive."""
+ releases = {
+ (release.binarypackagename, release.binpackageformat): release
+ for release in self.ci_build.binarypackages}
+ binaries = OrderedDict()
+ for scanned_artifact in scanned:
+ library_file = scanned_artifact.artifact.library_file
+ metadata = dict(scanned_artifact.metadata)
+ binpackageformat = metadata["binpackageformat"]
+ logger.info(
+ "Uploading %s to %s %s (%s)",
+ library_file.filename, self.archive.reference,
+ self.target_distroseries.getSuite(self.target_pocket),
+ self.target_channel)
+ metadata["binarypackagename"] = bpn = (
+ getUtility(IBinaryPackageNameSet).ensure(metadata["name"]))
+ del metadata["name"]
+ filetype = self.filetype_by_format[binpackageformat]
+ bpr = releases.get((bpn, binpackageformat))
+ if bpr is None:
+ bpr = self.ci_build.createBinaryPackageRelease(**metadata)
+ for bpf in bpr.files:
+ if (bpf.libraryfile == library_file and
+ bpf.filetype == filetype):
+ break
+ else:
+ bpr.addFile(library_file, filetype=filetype)
+ # The publishBinaries interface was designed for .debs,
+ # which need extra per-binary "override" information
+ # (component, etc.). None of this is relevant here.
+ binaries[bpr] = (None, None, None, None)
+ getUtility(IPublishingSet).publishBinaries(
+ self.archive, self.target_distroseries, self.target_pocket,
+ binaries, channel=self.target_channel)
+
+ def run(self):
+ """See `IRunnableJob`."""
+ build_target = self.ci_build.git_repository.target
+ if not IDistributionSourcePackage.providedBy(build_target):
+ # This should be caught by `Archive.uploadCIBuild`, but check it
+ # here as well just in case.
+ logger.warning(
+ "Source CI build is for %s, which is not a package",
+ repr(build_target))
+ return
+ artifacts = getUtility(IRevisionStatusArtifactSet).findByCIBuild(
+ self.ci_build)
+ scanned = self._scanArtifacts(artifacts)
+ if scanned:
+ self._uploadBinaries(scanned)
Follow ups