← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~ilasc/launchpad:add-get-snapbuild-by-revision into launchpad:master

 

Ioana Lasc has proposed merging ~ilasc/launchpad:add-get-snapbuild-by-revision into launchpad:master with ~ilasc/launchpad:populate-store-upload-revision as a prerequisite.

Commit message:
Add getBuildByStoreRevision to Snap

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

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

This needs the new column "_store_upload_revision" to be added to SnapBuild and populated (prerequisite branch: populate-store-upload-revision).
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~ilasc/launchpad:add-get-snapbuild-by-revision into launchpad:master.
diff --git a/lib/lp/snappy/interfaces/snap.py b/lib/lp/snappy/interfaces/snap.py
index 2445553..43e6be8 100644
--- a/lib/lp/snappy/interfaces/snap.py
+++ b/lib/lp/snappy/interfaces/snap.py
@@ -527,6 +527,20 @@ class ISnapView(Interface):
             given snap builds.
         """
 
+    @operation_parameters(
+        store_upload_revision=Int(title="Store revision",
+                                  required=True))
+    @export_read_operation()
+    @operation_for_version("devel")
+    def getBuildByStoreRevision(store_upload_revision, user=None):
+        """Returns the build (if any) of that snap recipe
+            that has the given store_upload_revision.
+
+        :param store_upload_revision: The revision assigned by the store.
+        :param user: The `IPerson` requesting this information.
+        :return: An 'ISnapBuild' or None.
+        """
+
     @call_with(user=REQUEST_USER)
     @operation_parameters(
         request_ids=List(
diff --git a/lib/lp/snappy/model/snap.py b/lib/lp/snappy/model/snap.py
index 24aa2be..ed82ca3 100644
--- a/lib/lp/snappy/model/snap.py
+++ b/lib/lp/snappy/model/snap.py
@@ -1111,6 +1111,13 @@ class Snap(Storm, WebhookTargetMixin):
 
         return result
 
+    def getBuildByStoreRevision(self, store_upload_revision):
+       build = Store.of(self).find(
+           SnapBuild,
+           SnapBuild.snap == self,
+           SnapBuild._store_upload_revision == store_upload_revision).one()
+       return build
+
     @property
     def builds(self):
         """See `ISnap`."""
diff --git a/lib/lp/snappy/model/snapbuildjob.py b/lib/lp/snappy/model/snapbuildjob.py
index 9634f62..a8fc49f 100644
--- a/lib/lp/snappy/model/snapbuildjob.py
+++ b/lib/lp/snappy/model/snapbuildjob.py
@@ -263,6 +263,7 @@ class SnapStoreUploadJob(SnapBuildJobDerived):
         if self.snapbuild.store_upload_metadata is None:
             self.snapbuild.store_upload_metadata = {}
         self.snapbuild.store_upload_metadata["store_revision"] = revision
+        self.snapbuild._store_upload_revision = revision
 
     @property
     def status_url(self):
diff --git a/lib/lp/snappy/tests/test_snap.py b/lib/lp/snappy/tests/test_snap.py
index 4d9c92f..adb8cfa 100644
--- a/lib/lp/snappy/tests/test_snap.py
+++ b/lib/lp/snappy/tests/test_snap.py
@@ -125,6 +125,7 @@ from lp.snappy.interfaces.snapbase import (
 from lp.snappy.interfaces.snapbuild import (
     ISnapBuild,
     ISnapBuildSet,
+    SnapBuildStoreUploadStatus,
     )
 from lp.snappy.interfaces.snapbuildjob import ISnapStoreUploadJobSource
 from lp.snappy.interfaces.snapjob import ISnapRequestBuildsJobSource
@@ -137,6 +138,10 @@ from lp.snappy.model.snap import (
 from lp.snappy.model.snapbuild import SnapFile
 from lp.snappy.model.snapbuildjob import SnapBuildJob
 from lp.snappy.model.snapjob import SnapJob
+from lp.snappy.tests.test_snapbuildjob import (
+    FakeSnapStoreClient,
+    run_isolated_jobs,
+    )
 from lp.testing import (
     admin_logged_in,
     ANONYMOUS,
@@ -1079,6 +1084,50 @@ class TestSnap(TestCaseWithFactory):
             snap.destroySelf()
         self.assertFalse(getUtility(ISnapSet).exists(owner, "condemned"))
 
+    def test_getBuildByStoreRevision(self):
+        snap1 = self.factory.makeSnap()
+        build = self.factory.makeSnapBuild(
+            snap=snap1,
+            status=BuildStatus.FULLYBUILT)
+
+        # There is no build with revision 5 for snap1
+        self.assertIsNone(snap1.getBuildByStoreRevision(5))
+
+        # Upload build1 and check we return it by version 1
+        job = getUtility(ISnapStoreUploadJobSource).create(build)
+        client = FakeSnapStoreClient()
+        client.upload.result = (
+            "http://sca.example/dev/api/snaps/1/builds/1/status";)
+        client.checkStatus.result = (
+            "http://sca.example/dev/click-apps/1/rev/1/";, 1)
+        self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient))
+        with dbuser(config.ISnapStoreUploadJobSource.dbuser):
+            run_isolated_jobs([job])
+        self.assertEqual(
+            SnapBuildStoreUploadStatus.UPLOADED, build.store_upload_status)
+        self.assertEqual(build.store_upload_revision, 1)
+        self.assertEqual(snap1.getBuildByStoreRevision(1), build)
+
+        # build & upload again, check revision
+        # and that we return the second build for revision 2
+        build2 = self.factory.makeSnapBuild(
+            snap=snap1,
+            status=BuildStatus.FULLYBUILT)
+        job = getUtility(ISnapStoreUploadJobSource).create(build2)
+        client = FakeSnapStoreClient()
+        client.upload.result = (
+            "http://sca.example/dev/api/snaps/1/builds/2/status";)
+        client.checkStatus.result = (
+            "http://sca.example/dev/click-apps/1/rev/2/";, 2)
+        self.useFixture(ZopeUtilityFixture(client, ISnapStoreClient))
+        with dbuser(config.ISnapStoreUploadJobSource.dbuser):
+            run_isolated_jobs([job])
+        self.assertEqual(
+            SnapBuildStoreUploadStatus.UPLOADED, build2.store_upload_status)
+        self.assertEqual(build2.store_upload_revision, 2)
+        self.assertEqual(snap1.getBuildByStoreRevision(2), build2)
+        self.assertEqual(snap1.getBuildByStoreRevision(1), build)
+
     def test_getBuildSummariesForSnapBuildIds(self):
         snap1 = self.factory.makeSnap()
         snap2 = self.factory.makeSnap()