← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:refactor-spr-creation into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:refactor-spr-creation into launchpad:master.

Commit message:
Refactor SourcePackageRelease creation for CI builds

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/426398

DB patch 2210-44-0 added support for `SourcePackageRelease` rows based on `CIBuild`s, but that wasn't yet reflected in the ORM model.  Add the new `ci_build` column, and rearrange `SourcePackageRelease` and `SourcePackagePublishingHistory` creation methods so that dpkg-specific arguments are optional.

(This is a clear case where `black`'s formatting would have made the diff more concise, but we haven't got as far as `lp.registry` and `lp.soyuz` there yet.)
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:refactor-spr-creation into launchpad:master.
diff --git a/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.rst b/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.rst
index bc91675..ec6ddf1 100644
--- a/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.rst
+++ b/lib/lp/archiveuploader/tests/nascentupload-epoch-handling.rst
@@ -221,8 +221,9 @@ For source uploads, Changes.version == DSC.version == SPR.version:
     >>> from lp.soyuz.interfaces.publishing import IPublishingSet
     >>> getUtility(IPublishingSet).newSourcePublication(
     ...     bar_src_upload.policy.distro.main_archive, bar_spr,
-    ...     bar_src_upload.policy.distroseries, bar_spr.component,
-    ...     bar_spr.section, PackagePublishingPocket.RELEASE)
+    ...     bar_src_upload.policy.distroseries,
+    ...     PackagePublishingPocket.RELEASE,
+    ...     component=bar_spr.component, section=bar_spr.section)
     <SourcePackagePublishingHistory at ...>
 
 Let's accept the source and claim 'build from accepted' to process the
diff --git a/lib/lp/archiveuploader/tests/nascentupload.rst b/lib/lp/archiveuploader/tests/nascentupload.rst
index 2931a2a..101c900 100644
--- a/lib/lp/archiveuploader/tests/nascentupload.rst
+++ b/lib/lp/archiveuploader/tests/nascentupload.rst
@@ -546,8 +546,8 @@ Then the source gets accepted and published, step 3 and 4:
     >>> from lp.soyuz.interfaces.publishing import IPublishingSet
     >>> getUtility(IPublishingSet).newSourcePublication(
     ...     multibar_src_queue.archive, multibar_spr,
-    ...     sync_policy.distroseries, multibar_spr.component,
-    ...     multibar_spr.section, PackagePublishingPocket.RELEASE)
+    ...     sync_policy.distroseries, PackagePublishingPocket.RELEASE,
+    ...     component=multibar_spr.component, section=multibar_spr.section)
     <SourcePackagePublishingHistory at ...>
 
 Build creation is done based on the SourcePackageRelease object, step 5:
diff --git a/lib/lp/archiveuploader/tests/test_buildduploads.py b/lib/lp/archiveuploader/tests/test_buildduploads.py
index 3070282..8fced97 100644
--- a/lib/lp/archiveuploader/tests/test_buildduploads.py
+++ b/lib/lp/archiveuploader/tests/test_buildduploads.py
@@ -215,9 +215,9 @@ class TestBuilddUploads(TestStagedBinaryUploadBase):
             self.distroseries.main_archive,
             spr,
             self.distroseries,
-            spr.component,
-            spr.section,
             PackagePublishingPocket.RELEASE,
+            component=spr.component,
+            section=spr.section,
         )
         self.policy = real_policy
 
diff --git a/lib/lp/registry/interfaces/distroseries.py b/lib/lp/registry/interfaces/distroseries.py
index 7573194..66a5479 100644
--- a/lib/lp/registry/interfaces/distroseries.py
+++ b/lib/lp/registry/interfaces/distroseries.py
@@ -671,56 +671,57 @@ class IDistroSeriesPublic(
         """
 
     def createUploadedSourcePackageRelease(
-        sourcepackagename, version, format, maintainer, builddepends,
-        builddependsindep, architecturehintlist, component, creator, urgency,
-        changelog, changelog_entry, dsc, dscsigningkey, section,
-        dsc_maintainer_rfc822, dsc_standards_version, dsc_format,
-        dsc_binaries, archive, copyright, build_conflicts,
-        build_conflicts_indep, dateuploaded=None,
-        source_package_recipe_build=None, user_defined_fields=None,
-        homepage=None, buildinfo=None):
-        """Create an uploads `SourcePackageRelease`.
-
-        Set this distroseries set to be the uploadeddistroseries.
-
-        All arguments are mandatory, they are extracted/built when
-        processing and uploaded source package:
-
-         :param dateuploaded: timestamp, if not provided will be UTC_NOW
-         :param sourcepackagename: `ISourcePackageName`
-         :param version: string, a debian valid version
-         :param format: `SourcePackageType`
-         :param maintainer: IPerson designed as package maintainer
-         :param creator: IPerson, package uploader
-         :param component: IComponent
-         :param section: ISection
-         :param urgency: dbschema.SourcePackageUrgency
-         :param dscsigningkey: IGPGKey used to sign the DSC file
-         :param dsc: string, original content of the dsc file
-         :param copyright: string, the original debian/copyright content
-         :param changelog: LFA ID of the debian/changelog file in librarian
-         :param changelog_entry: string, changelog extracted from the
-                                 changesfile
-         :param architecturehintlist: string, DSC architectures
-         :param builddepends: string, DSC build dependencies
-         :param builddependsindep: string, DSC architecture independent build
-                                   dependencies.
-         :param build_conflicts: string, DSC Build-Conflicts content
-         :param build_conflicts_indep: string, DSC Build-Conflicts-Indep
-                                       content
-         :param dsc_maintainer_rfc822: string, DSC maintainer field
-         :param dsc_standards_version: string, DSC standards version field
-         :param dsc_format: string, DSC format version field
-         :param dsc_binaries:  string, DSC binaries field
-         :param archive: IArchive to where the upload was targeted
-         :param dateuploaded: optional datetime, if omitted assumed nowUTC
-         :param source_package_recipe_build: optional SourcePackageRecipeBuild
-         :param user_defined_fields: optional sequence of key-value pairs with
-                                     user defined fields.
-         :param homepage: optional string with (unchecked) upstream homepage
-                          URL
-         :param buildinfo: optional LFA with build information file
-         :return: the just creates `SourcePackageRelease`
+        sourcepackagename, version, format, architecturehintlist, creator,
+        archive, maintainer=None, component=None, section=None, urgency=None,
+        dscsigningkey=None, dsc=None, copyright=None, changelog=None,
+        changelog_entry=None, builddepends=None, builddependsindep=None,
+        build_conflicts=None, build_conflicts_indep=None,
+        dsc_maintainer_rfc822=None, dsc_standards_version=None,
+        dsc_format=None, dsc_binaries=None, dateuploaded=None,
+        source_package_recipe_build=None, ci_build=None,
+        user_defined_fields=None, homepage=None, buildinfo=None):
+        """Create an uploaded `SourcePackageRelease`.
+
+        Set this distroseries to be the `upload_distroseries`.
+
+        Arguments are extracted/built when processing an uploaded source
+        package:
+
+        :param sourcepackagename: `ISourcePackageName`
+        :param version: string, a valid Debian version
+        :param format: `SourcePackageType`
+        :param architecturehintlist: string, DSC architectures
+        :param creator: `IPerson`, package uploader
+        :param archive: `IArchive` to where the upload was targeted
+        :param maintainer: `IPerson` designated as package maintainer
+        :param component: `IComponent`
+        :param section: `ISection`
+        :param urgency: `SourcePackageUrgency`
+        :param dscsigningkey: `IGPGKey` used to sign the DSC file
+        :param dsc: string, original content of the dsc file
+        :param copyright: string, the original debian/copyright content
+        :param changelog: LFA ID of the debian/changelog file in librarian
+        :param changelog_entry: string, changelog extracted from the
+                                changesfile
+        :param builddepends: string, DSC build dependencies
+        :param builddependsindep: string, DSC architecture independent build
+                                  dependencies
+        :param build_conflicts: string, DSC Build-Conflicts content
+        :param build_conflicts_indep: string, DSC Build-Conflicts-Indep
+                                      content
+        :param dsc_maintainer_rfc822: string, DSC maintainer field
+        :param dsc_standards_version: string, DSC standards version field
+        :param dsc_format: string, DSC format version field
+        :param dsc_binaries: string, DSC binaries field
+        :param dateuploaded: optional datetime, if omitted assumed `UTC_NOW`
+        :param source_package_recipe_build: optional `SourcePackageRecipeBuild`
+        :param ci_build: optional `CIBuild`
+        :param user_defined_fields: optional sequence of key-value pairs with
+                                    user defined fields
+        :param homepage: optional string with (unchecked) upstream homepage
+                         URL
+        :param buildinfo: optional LFA with build information file
+        :return: the new `SourcePackageRelease`
         """
 
     def getComponentByName(name):
diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py
index 46fb381..aff2b47 100644
--- a/lib/lp/registry/model/distroseries.py
+++ b/lib/lp/registry/model/distroseries.py
@@ -1060,14 +1060,15 @@ class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin,
             self, build_state, name, pocket, arch_tag)
 
     def createUploadedSourcePackageRelease(
-        self, sourcepackagename, version, format, maintainer, builddepends,
-        builddependsindep, architecturehintlist, component, creator,
-        urgency, changelog, changelog_entry, dsc, dscsigningkey, section,
-        dsc_maintainer_rfc822, dsc_standards_version, dsc_format,
-        dsc_binaries, archive, copyright, build_conflicts,
-        build_conflicts_indep, dateuploaded=DEFAULT,
-        source_package_recipe_build=None, user_defined_fields=None,
-        homepage=None, buildinfo=None):
+        self, sourcepackagename, version, format, architecturehintlist,
+        creator, archive, maintainer=None, component=None, section=None,
+        urgency=None, dscsigningkey=None, dsc=None, copyright=None,
+        changelog=None, changelog_entry=None, builddepends=None,
+        builddependsindep=None, build_conflicts=None,
+        build_conflicts_indep=None, dsc_maintainer_rfc822=None,
+        dsc_standards_version=None, dsc_format=None, dsc_binaries=None,
+        dateuploaded=DEFAULT, source_package_recipe_build=None, ci_build=None,
+        user_defined_fields=None, homepage=None, buildinfo=None):
         """See `IDistroSeries`."""
         return SourcePackageRelease(
             upload_distroseries=self, sourcepackagename=sourcepackagename,
@@ -1087,8 +1088,8 @@ class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin,
             build_conflicts=build_conflicts,
             build_conflicts_indep=build_conflicts_indep,
             source_package_recipe_build=source_package_recipe_build,
-            user_defined_fields=user_defined_fields, homepage=homepage,
-            buildinfo=buildinfo)
+            ci_build=ci_build, user_defined_fields=user_defined_fields,
+            homepage=homepage, buildinfo=buildinfo)
 
     def getComponentByName(self, name):
         """See `IDistroSeries`."""
diff --git a/lib/lp/soyuz/doc/publishing.rst b/lib/lp/soyuz/doc/publishing.rst
index fb5cf2b..d0169d7 100644
--- a/lib/lp/soyuz/doc/publishing.rst
+++ b/lib/lp/soyuz/doc/publishing.rst
@@ -1031,9 +1031,9 @@ the PPA publication will always be main:
     ...     archive=mark.archive,
     ...     sourcepackagerelease=test_source_pub.sourcepackagerelease,
     ...     distroseries=mark.archive.distribution.currentseries,
+    ...     pocket=test_source_pub.pocket,
     ...     component=test_source_pub.component,
-    ...     section=test_source_pub.section,
-    ...     pocket=test_source_pub.pocket)
+    ...     section=test_source_pub.section)
     >>> print(ppa_pub.component.name)
     main
 
diff --git a/lib/lp/soyuz/doc/sourcepackagerelease.rst b/lib/lp/soyuz/doc/sourcepackagerelease.rst
index d082b01..1acf131 100644
--- a/lib/lp/soyuz/doc/sourcepackagerelease.rst
+++ b/lib/lp/soyuz/doc/sourcepackagerelease.rst
@@ -167,13 +167,31 @@ ISourcePackageRelease, it will automatically set the
 'upload_distroseries' to the API entry point, in this case Hoary.
 
     >>> new_spr = hoary.createUploadedSourcePackageRelease(
-    ...     arg_name, version, SourcePackageType.DPKG, arg_maintainer,
-    ...     builddepends, builddependsindep, archhintlist, arg_comp,
-    ...     arg_creator, arg_urgency, changelog, changelog_entry, dsc,
-    ...     arg_key, arg_sect, dsc_maintainer_rfc822, dsc_standards_version,
-    ...     dsc_format, dsc_binaries, archive, copyright=copyright,
-    ...     build_conflicts=None, build_conflicts_indep=None,
-    ...     source_package_recipe_build=arg_recipebuild)
+    ...     sourcepackagename=arg_name,
+    ...     version=version,
+    ...     format=SourcePackageType.DPKG,
+    ...     maintainer=arg_maintainer,
+    ...     builddepends=builddepends,
+    ...     builddependsindep=builddependsindep,
+    ...     architecturehintlist=archhintlist,
+    ...     component=arg_comp,
+    ...     creator=arg_creator,
+    ...     urgency=arg_urgency,
+    ...     changelog=changelog,
+    ...     changelog_entry=changelog_entry,
+    ...     dsc=dsc,
+    ...     dscsigningkey=arg_key,
+    ...     section=arg_sect,
+    ...     dsc_maintainer_rfc822=dsc_maintainer_rfc822,
+    ...     dsc_standards_version=dsc_standards_version,
+    ...     dsc_format=dsc_format,
+    ...     dsc_binaries=dsc_binaries,
+    ...     archive=archive,
+    ...     copyright=copyright,
+    ...     build_conflicts=None,
+    ...     build_conflicts_indep=None,
+    ...     source_package_recipe_build=arg_recipebuild,
+    ... )
 
     >>> print(new_spr.upload_distroseries.name)
     hoary
diff --git a/lib/lp/soyuz/interfaces/publishing.py b/lib/lp/soyuz/interfaces/publishing.py
index 95ddb5d..9561f6b 100644
--- a/lib/lp/soyuz/interfaces/publishing.py
+++ b/lib/lp/soyuz/interfaces/publishing.py
@@ -986,17 +986,17 @@ class IPublishingSet(Interface):
         """
 
     def newSourcePublication(archive, sourcepackagerelease, distroseries,
-                             component, section, pocket, ancestor,
-                             create_dsd_job=True, copied_from_archive=None,
-                             creator=None, sponsor=None, packageupload=None,
-                             channel=None):
+                             pocket, component=None, section=None,
+                             ancestor=None, create_dsd_job=True,
+                             copied_from_archive=None, creator=None,
+                             sponsor=None, packageupload=None, channel=None):
         """Create a new `SourcePackagePublishingHistory`.
 
         :param archive: An `IArchive`
         :param sourcepackagerelease: An `ISourcePackageRelease`
         :param distroseries: An `IDistroSeries`
-        :param component: An `IComponent`
-        :param section: An `ISection`
+        :param component: An `IComponent` (optional for SPR.format != DPKG)
+        :param section: An `ISection` (optional for SPR.format != DPKG)
         :param pocket: A `PackagePublishingPocket`
         :param ancestor: A `ISourcePackagePublishingHistory` for the previous
             version of this publishing record
diff --git a/lib/lp/soyuz/model/publishing.py b/lib/lp/soyuz/model/publishing.py
index b7f7e3f..2134570 100644
--- a/lib/lp/soyuz/model/publishing.py
+++ b/lib/lp/soyuz/model/publishing.py
@@ -141,6 +141,8 @@ def get_component(archive, distroseries, component):
 
     If there is no default, just return the given component.
     """
+    if component is None:
+        return None
     permitted_components = archive.getComponentsForSeries(distroseries)
     if (component not in permitted_components and
         archive.default_component is not None):
@@ -580,9 +582,9 @@ class SourcePackagePublishingHistory(SQLBase, ArchivePublisherBase):
             archive,
             self.sourcepackagerelease,
             distroseries,
-            component,
-            section,
             pocket,
+            component=component,
+            section=section,
             ancestor=self,
             create_dsd_job=create_dsd_job,
             creator=creator,
@@ -1309,8 +1311,8 @@ class PublishingSet:
             copied_from_archives, channel=channel)
 
     def newSourcePublication(self, archive, sourcepackagerelease,
-                             distroseries, component, section, pocket,
-                             ancestor=None, create_dsd_job=True,
+                             distroseries, pocket, component=None,
+                             section=None, ancestor=None, create_dsd_job=True,
                              copied_from_archive=None,
                              creator=None, sponsor=None, packageupload=None,
                              channel=None):
@@ -1334,6 +1336,14 @@ class PublishingSet:
                     "Channel publications must be in the RELEASE pocket")
             channel = channel_string_to_list(channel)
 
+        if sourcepackagerelease.format == SourcePackageType.DPKG:
+            if component is None:
+                raise AssertionError(
+                    "dpkg source publications require a component")
+            if section is None:
+                raise AssertionError(
+                    "dpkg source publications require a section")
+
         pub = SourcePackagePublishingHistory(
             distroseries=distroseries,
             pocket=pocket,
diff --git a/lib/lp/soyuz/model/queue.py b/lib/lp/soyuz/model/queue.py
index 4e85e04..954a928 100644
--- a/lib/lp/soyuz/model/queue.py
+++ b/lib/lp/soyuz/model/queue.py
@@ -1416,9 +1416,9 @@ class PackageUploadSource(StormBase):
             archive=self.packageupload.archive,
             sourcepackagerelease=self.sourcepackagerelease,
             distroseries=self.packageupload.distroseries,
+            pocket=self.packageupload.pocket,
             component=self.sourcepackagerelease.component,
             section=self.sourcepackagerelease.section,
-            pocket=self.packageupload.pocket,
             packageupload=self.packageupload)
 
 
diff --git a/lib/lp/soyuz/model/sourcepackagerelease.py b/lib/lp/soyuz/model/sourcepackagerelease.py
index 78cbb7c..286b780 100644
--- a/lib/lp/soyuz/model/sourcepackagerelease.py
+++ b/lib/lp/soyuz/model/sourcepackagerelease.py
@@ -120,9 +120,14 @@ class SourcePackageRelease(SQLBase):
     upload_archive = ForeignKey(
         foreignKey='Archive', dbName='upload_archive', notNull=True)
 
-    source_package_recipe_build_id = Int(name='sourcepackage_recipe_build')
+    # DB constraint: at most one of source_package_recipe_build and ci_build
+    # is non-NULL.
+    source_package_recipe_build_id = Int(
+        name='sourcepackage_recipe_build', allow_none=True)
     source_package_recipe_build = Reference(
         source_package_recipe_build_id, 'SourcePackageRecipeBuild.id')
+    ci_build_id = Int(name='ci_build', allow_none=True)
+    ci_build = Reference(ci_build_id, 'CIBuild.id')
 
     # XXX cprov 2006-09-26: Those fields are set as notNull and required in
     # ISourcePackageRelease, however they can't be not NULL in DB since old
diff --git a/lib/lp/soyuz/scripts/gina/handlers.py b/lib/lp/soyuz/scripts/gina/handlers.py
index b809f93..9715576 100644
--- a/lib/lp/soyuz/scripts/gina/handlers.py
+++ b/lib/lp/soyuz/scripts/gina/handlers.py
@@ -692,9 +692,9 @@ class SourcePackagePublisher:
         entry = getUtility(IPublishingSet).newSourcePublication(
             distroseries=self.distroseries,
             sourcepackagerelease=sourcepackagerelease,
+            pocket=self.pocket,
             component=component,
             section=section,
-            pocket=self.pocket,
             archive=archive)
         entry.setPublished()
         log.info('Source package %s (%s) published' % (
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index a313f40..61c3b2d 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -3846,6 +3846,7 @@ class BareLaunchpadObjectFactory(ObjectFactory):
                                  dsc_format='1.0', dsc_binaries='foo-bin',
                                  date_uploaded=UTC_NOW,
                                  source_package_recipe_build=None,
+                                 ci_build=None,
                                  dscsigningkey=None,
                                  user_defined_fields=None,
                                  changelog_entry=None,
@@ -3857,6 +3858,8 @@ class BareLaunchpadObjectFactory(ObjectFactory):
         if distroseries is None:
             if source_package_recipe_build is not None:
                 distroseries = source_package_recipe_build.distroseries
+            elif ci_build is not None:
+                distroseries = ci_build.distro_series
             else:
                 if archive is None:
                     distribution = None
@@ -3928,6 +3931,7 @@ class BareLaunchpadObjectFactory(ObjectFactory):
             archive=archive,
             dateuploaded=date_uploaded,
             source_package_recipe_build=source_package_recipe_build,
+            ci_build=ci_build,
             user_defined_fields=user_defined_fields,
             homepage=homepage)
 
@@ -4086,9 +4090,10 @@ class BareLaunchpadObjectFactory(ObjectFactory):
         admins = getUtility(ILaunchpadCelebrities).admin
         with person_logged_in(admins.teamowner):
             spph = getUtility(IPublishingSet).newSourcePublication(
-                archive, sourcepackagerelease, distroseries,
-                sourcepackagerelease.component, sourcepackagerelease.section,
-                pocket, ancestor=ancestor, creator=creator,
+                archive, sourcepackagerelease, distroseries, pocket,
+                component=sourcepackagerelease.component,
+                section=sourcepackagerelease.section,
+                ancestor=ancestor, creator=creator,
                 packageupload=packageupload, channel=channel)
 
         naked_spph = removeSecurityProxy(spph)