← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/snap-preferred-series into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/snap-preferred-series into lp:launchpad.

Commit message:
Add a preferred distro series to SnappySeries, which is used to choose the default series on {Branch,GitRef}:+new-snap.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/snap-preferred-series/+merge/310216

At the moment, {Branch,GitRef}:+new-snap defaults the series to one associated with ubuntu.currentseries; but snaps built from yakkety end up needing to bundle libc since it's newer, so that isn't a great default.  Introducing the concept of a preferred distribution series associated with each snappy series lets us do something more reasonable here while still making it possible for people to experiment with newer series.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/snap-preferred-series into lp:launchpad.
=== modified file 'lib/lp/snappy/browser/snap.py'
--- lib/lp/snappy/browser/snap.py	2016-07-26 20:55:37 +0000
+++ lib/lp/snappy/browser/snap.py	2016-11-07 18:18:48 +0000
@@ -48,7 +48,6 @@
 from lp.app.browser.tales import format_link
 from lp.app.enums import PRIVATE_INFORMATION_TYPES
 from lp.app.interfaces.informationtype import IInformationType
-from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.app.widgets.itemswidgets import (
     LabeledMultiCheckBoxWidget,
     LaunchpadDropdownWidget,
@@ -93,7 +92,10 @@
     SnapPrivateFeatureDisabled,
     )
 from lp.snappy.interfaces.snapbuild import ISnapBuildSet
-from lp.snappy.interfaces.snappyseries import ISnappyDistroSeriesSet
+from lp.snappy.interfaces.snappyseries import (
+    ISnappyDistroSeriesSet,
+    ISnappySeriesSet,
+    )
 from lp.snappy.interfaces.snapstoreclient import (
     BadRequestPackageUploadResponse,
     ISnapStoreClient,
@@ -458,19 +460,23 @@
                     "Failed to extract name from Snap manifest at Git %s: %s",
                     self.context.unique_name, unicode(e))
 
-        # XXX cjwatson 2015-09-18: Hack to ensure that we don't end up
-        # accidentally selecting ubuntu-rtm/14.09 or similar.
-        # ubuntu.currentseries will always be in BuildableDistroSeries.
-        series = getUtility(ILaunchpadCelebrities).ubuntu.currentseries
+        store_series = getUtility(ISnappySeriesSet).getAll().first()
+        if store_series.preferred_distro_series is not None:
+            distro_series = store_series.preferred_distro_series
+        else:
+            distro_series = store_series.usable_distro_series.first()
         sds_set = getUtility(ISnappyDistroSeriesSet)
+        store_distro_series = sds_set.getByBothSeries(
+            store_series, distro_series)
+
         return {
             'store_name': store_name,
             'owner': self.user,
-            'store_distro_series': sds_set.getByDistroSeries(series).first(),
+            'store_distro_series': store_distro_series,
             'processors': [
                 p for p in getUtility(IProcessorSet).getAll()
                 if p.build_by_default],
-            'auto_build_archive': series.main_archive,
+            'auto_build_archive': distro_series.main_archive,
             'auto_build_pocket': PackagePublishingPocket.UPDATES,
             }
 

=== modified file 'lib/lp/snappy/browser/tests/test_snap.py'
--- lib/lp/snappy/browser/tests/test_snap.py	2016-09-07 11:12:58 +0000
+++ lib/lp/snappy/browser/tests/test_snap.py	2016-11-07 18:18:48 +0000
@@ -154,7 +154,7 @@
             version="13.10")
         with admin_logged_in():
             self.snappyseries = self.factory.makeSnappySeries(
-                usable_distro_series=[self.distroseries])
+                preferred_distro_series=self.distroseries)
         self.snap_store_client = FakeMethod()
         self.snap_store_client.listChannels = FakeMethod(result=[
             {"name": "stable", "display_name": "Stable"},
@@ -175,7 +175,7 @@
                 distroseries=distroseries, architecturetag=name,
                 processor=processor)
         with admin_logged_in():
-            self.factory.makeSnappySeries(usable_distro_series=[distroseries])
+            self.factory.makeSnappySeries(preferred_distro_series=distroseries)
         return distroseries
 
     def assertProcessorControls(self, processors_control, enabled, disabled):
@@ -187,29 +187,25 @@
             for name in disabled])
         self.assertThat(processors_control.controls, MatchesSetwise(*matchers))
 
-    def test_initial_distroseries(self):
-        # The initial distroseries is the newest that is current or in
-        # development.
-        old = self.factory.makeUbuntuDistroSeries(
-            version="14.04", status=SeriesStatus.DEVELOPMENT)
-        development = self.factory.makeUbuntuDistroSeries(
-            version="14.10", status=SeriesStatus.DEVELOPMENT)
-        experimental = self.factory.makeUbuntuDistroSeries(
-            version="15.04", status=SeriesStatus.EXPERIMENTAL)
+    def test_initial_store_distro_series(self):
+        # The initial store_distro_series uses the preferred distribution
+        # series for the latest snappy series.
+        lts = self.factory.makeUbuntuDistroSeries(
+            version="16.04", status=SeriesStatus.CURRENT)
+        current = self.factory.makeUbuntuDistroSeries(
+            version="16.10", status=SeriesStatus.CURRENT)
         with admin_logged_in():
-            self.factory.makeSnappySeries(
-                usable_distro_series=[old, development, experimental])
+            self.factory.makeSnappySeries(usable_distro_series=[lts, current])
             newest = self.factory.makeSnappySeries(
-                usable_distro_series=[development, experimental])
-            self.factory.makeSnappySeries(
-                usable_distro_series=[old, experimental])
+                preferred_distro_series=lts,
+                usable_distro_series=[lts, current])
         branch = self.factory.makeAnyBranch()
         with person_logged_in(self.person):
             view = create_initialized_view(branch, "+new-snap")
         self.assertThat(
             view.initial_values["store_distro_series"],
             MatchesStructure.byEquality(
-                snappy_series=newest, distro_series=development))
+                snappy_series=newest, distro_series=lts))
 
     def test_create_new_snap_not_logged_in(self):
         branch = self.factory.makeAnyBranch()

=== modified file 'lib/lp/snappy/interfaces/snappyseries.py'
--- lib/lp/snappy/interfaces/snappyseries.py	2016-05-24 05:15:50 +0000
+++ lib/lp/snappy/interfaces/snappyseries.py	2016-11-07 18:18:48 +0000
@@ -107,6 +107,10 @@
     status = exported(Choice(
         title=_("Status"), required=True, vocabulary=SeriesStatus))
 
+    preferred_distro_series = exported(Reference(
+        IDistroSeries, title=_("Preferred distro series"),
+        required=False, readonly=False))
+
     usable_distro_series = exported(List(
         title=_("Usable distro series"),
         description=_(

=== modified file 'lib/lp/snappy/model/snappyseries.py'
--- lib/lp/snappy/model/snappyseries.py	2016-05-24 05:15:50 +0000
+++ lib/lp/snappy/model/snappyseries.py	2016-11-07 18:18:48 +0000
@@ -60,26 +60,48 @@
 
     status = EnumCol(enum=SeriesStatus, notNull=True)
 
+    preferred_distro_series_id = Int(
+        name='preferred_distro_series', allow_none=True)
+    _preferred_distro_series = Reference(
+        preferred_distro_series_id, 'DistroSeries.id')
+
     def __init__(self, registrant, name, display_name, status,
-                 date_created=DEFAULT):
+                 preferred_distro_series=None, date_created=DEFAULT):
         super(SnappySeries, self).__init__()
         self.registrant = registrant
         self.name = name
         self.display_name = display_name
         self.status = status
         self.date_created = date_created
+        self.preferred_distro_series = preferred_distro_series
 
     @property
     def title(self):
         return self.display_name
 
     @property
+    def preferred_distro_series(self):
+        return self._preferred_distro_series
+
+    @preferred_distro_series.setter
+    def preferred_distro_series(self, value):
+        if value is not None:
+            existing = Store.of(self).find(
+                SnappyDistroSeries,
+                SnappyDistroSeries.snappy_series == self,
+                SnappyDistroSeries.distro_series == value)
+            if existing.is_empty():
+                link = SnappyDistroSeries(self, value)
+                Store.of(self).add(link)
+        self._preferred_distro_series = value
+
+    @property
     def usable_distro_series(self):
         rows = IStore(DistroSeries).find(
             DistroSeries,
             SnappyDistroSeries.snappy_series == self,
             SnappyDistroSeries.distro_series_id == DistroSeries.id)
-        return rows.order_by(DistroSeries.id)
+        return rows.order_by(Desc(DistroSeries.id))
 
     @usable_distro_series.setter
     def usable_distro_series(self, value):
@@ -125,11 +147,13 @@
     """See `ISnappySeriesSet`."""
 
     def new(self, registrant, name, display_name, status,
-            date_created=DEFAULT):
+            preferred_distro_series=None, date_created=DEFAULT):
         """See `ISnappySeriesSet`."""
         store = IMasterStore(SnappySeries)
         snappy_series = SnappySeries(
-            registrant, name, display_name, status, date_created=date_created)
+            registrant, name, display_name, status,
+            preferred_distro_series=preferred_distro_series,
+            date_created=date_created)
         store.add(snappy_series)
         return snappy_series
 
@@ -160,7 +184,7 @@
     def getAll(self):
         """See `ISnappySeriesSet`."""
         return IStore(SnappySeries).find(SnappySeries).order_by(
-            SnappySeries.name)
+            Desc(SnappySeries.name))
 
 
 @implementer(ISnappyDistroSeriesSet)

=== modified file 'lib/lp/snappy/tests/test_snappyseries.py'
--- lib/lp/snappy/tests/test_snappyseries.py	2016-07-15 14:25:15 +0000
+++ lib/lp/snappy/tests/test_snappyseries.py	2016-11-07 18:18:48 +0000
@@ -58,6 +58,18 @@
         snappy_series = self.factory.makeSnappySeries()
         self.assertProvides(snappy_series, ISnappySeries)
 
+    def test_set_preferred_distro_series(self):
+        dses = [self.factory.makeDistroSeries() for _ in range(2)]
+        snappy_series = self.factory.makeSnappySeries(
+            usable_distro_series=[dses[0]])
+        self.assertIsNone(snappy_series.preferred_distro_series)
+        snappy_series.preferred_distro_series = dses[1]
+        self.assertEqual(dses[1], snappy_series.preferred_distro_series)
+        self.assertContentEqual(dses, snappy_series.usable_distro_series)
+        snappy_series.preferred_distro_series = dses[0]
+        self.assertEqual(dses[0], snappy_series.preferred_distro_series)
+        self.assertContentEqual(dses, snappy_series.usable_distro_series)
+
     def test_new_no_usable_distro_series(self):
         snappy_series = self.factory.makeSnappySeries()
         self.assertContentEqual([], snappy_series.usable_distro_series)

=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py	2016-11-03 15:07:36 +0000
+++ lib/lp/testing/factory.py	2016-11-07 18:18:48 +0000
@@ -4723,7 +4723,8 @@
 
     def makeSnappySeries(self, registrant=None, name=None, display_name=None,
                          status=SeriesStatus.DEVELOPMENT,
-                         date_created=DEFAULT, usable_distro_series=None):
+                         preferred_distro_series=None, date_created=DEFAULT,
+                         usable_distro_series=None):
         """Make a new SnappySeries."""
         if registrant is None:
             registrant = self.makePerson()
@@ -4733,9 +4734,13 @@
             display_name = SPACE.join(
                 word.capitalize() for word in name.split('-'))
         snappy_series = getUtility(ISnappySeriesSet).new(
-            registrant, name, display_name, status, date_created=date_created)
+            registrant, name, display_name, status,
+            preferred_distro_series=preferred_distro_series,
+            date_created=date_created)
         if usable_distro_series is not None:
             snappy_series.usable_distro_series = usable_distro_series
+        elif preferred_distro_series is not None:
+            snappy_series.usable_distro_series = [preferred_distro_series]
         IStore(snappy_series).flush()
         return snappy_series
 


Follow ups