← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/snap-build-request-date-attrs into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/snap-build-request-date-attrs into lp:launchpad.

Commit message:
Add and export SnapBuildRequest.date_requested and SnapBuildRequest.date_finished.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1770400 in Launchpad itself: "Support snapcraft architectures keyword"
  https://bugs.launchpad.net/launchpad/+bug/1770400

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/snap-build-request-date-attrs/+merge/352468

This will let build.snapcraft.io intersperse these appropriately with builds.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/snap-build-request-date-attrs into lp:launchpad.
=== modified file 'lib/lp/snappy/interfaces/snap.py'
--- lib/lp/snappy/interfaces/snap.py	2018-06-18 22:08:58 +0000
+++ lib/lp/snappy/interfaces/snap.py	2018-08-06 15:25:54 +0000
@@ -289,6 +289,14 @@
 
     id = Int(title=_("ID"), required=True, readonly=True)
 
+    date_requested = exported(Datetime(
+        title=_("The time when this request was made"),
+        required=True, readonly=True))
+
+    date_finished = exported(Datetime(
+        title=_("The time when this request finished"),
+        required=False, readonly=True))
+
     snap = exported(Reference(
         # Really ISnap, patched in lp.snappy.interfaces.webservice.
         Interface,

=== modified file 'lib/lp/snappy/interfaces/snapjob.py'
--- lib/lp/snappy/interfaces/snapjob.py	2018-06-15 13:21:14 +0000
+++ lib/lp/snappy/interfaces/snapjob.py	2018-08-06 15:25:54 +0000
@@ -19,6 +19,7 @@
     )
 from zope.schema import (
     Choice,
+    Datetime,
     Dict,
     List,
     TextLine,
@@ -74,6 +75,14 @@
             "supported."),
         key_type=TextLine(), required=False, readonly=True)
 
+    date_created = Datetime(
+        title=_("Time when this job was created."),
+        required=True, readonly=True)
+
+    date_finished = Datetime(
+        title=_("Time when this job finished."),
+        required=True, readonly=True)
+
     error_message = TextLine(
         title=_("Error message resulting from running this job."),
         required=False, readonly=True)

=== modified file 'lib/lp/snappy/model/snap.py'
--- lib/lp/snappy/model/snap.py	2018-07-30 09:07:30 +0000
+++ lib/lp/snappy/model/snap.py	2018-08-06 15:25:54 +0000
@@ -182,6 +182,16 @@
         self.id = id
 
     @property
+    def date_requested(self):
+        """See `ISnapBuildRequest`."""
+        return self._job.date_created
+
+    @property
+    def date_finished(self):
+        """See `ISnapBuildRequest`."""
+        return self._job.date_finished
+
+    @property
     def status(self):
         """See `ISnapBuildRequest`."""
         status_map = {

=== modified file 'lib/lp/snappy/model/snapjob.py'
--- lib/lp/snappy/model/snapjob.py	2018-06-15 13:21:14 +0000
+++ lib/lp/snappy/model/snapjob.py	2018-08-06 15:25:54 +0000
@@ -233,6 +233,16 @@
         return self.metadata["channels"]
 
     @property
+    def date_created(self):
+        """See `ISnapRequestBuildsJob`."""
+        return self.context.job.date_created
+
+    @property
+    def date_finished(self):
+        """See `ISnapRequestBuildsJob`."""
+        return self.context.job.date_finished
+
+    @property
     def error_message(self):
         """See `ISnapRequestBuildsJob`."""
         return self.metadata.get("error_message")

=== modified file 'lib/lp/snappy/tests/test_snap.py'
--- lib/lp/snappy/tests/test_snap.py	2018-07-30 09:07:30 +0000
+++ lib/lp/snappy/tests/test_snap.py	2018-08-06 15:25:54 +0000
@@ -16,6 +16,7 @@
 from urlparse import urlsplit
 
 from fixtures import MockPatch
+import iso8601
 from lazr.lifecycle.event import ObjectModifiedEvent
 from pymacaroons import Macaroon
 import pytz
@@ -26,7 +27,10 @@
     AfterPreprocessing,
     ContainsDict,
     Equals,
+    GreaterThan,
     Is,
+    LessThan,
+    MatchesAll,
     MatchesDict,
     MatchesSetwise,
     MatchesStructure,
@@ -65,7 +69,10 @@
     UTC_NOW,
     )
 from lp.services.database.interfaces import IStore
-from lp.services.database.sqlbase import flush_database_caches
+from lp.services.database.sqlbase import (
+    flush_database_caches,
+    get_transaction_timestamp,
+    )
 from lp.services.features.testing import (
     FeatureFixture,
     MemoryFeatureFixture,
@@ -372,12 +379,15 @@
         # requestBuilds schedules a job and returns a corresponding
         # SnapBuildRequest.
         snap = self.factory.makeSnap()
+        now = get_transaction_timestamp(IStore(snap))
         with person_logged_in(snap.owner.teamowner):
             request = snap.requestBuilds(
                 snap.owner.teamowner, snap.distro_series.main_archive,
                 PackagePublishingPocket.UPDATES,
                 channels={"snapcraft": "edge"})
         self.assertThat(request, MatchesStructure(
+            date_requested=Equals(now),
+            date_finished=Is(None),
             snap=Equals(snap),
             status=Equals(SnapBuildRequestStatus.PENDING),
             error_message=Is(None),
@@ -434,6 +444,9 @@
               - build-on: avr
             """)))
         job = self.makeRequestBuildsJob(["sparc"])
+        self.assertEqual(
+            get_transaction_timestamp(IStore(job.snap)), job.date_created)
+        transaction.commit()
         with person_logged_in(job.requester):
             builds = job.snap.requestBuildsFromJob(
                 job.requester, job.archive, job.pocket,
@@ -446,6 +459,9 @@
         # architectures.
         self.useFixture(GitHostingFixture(blob="name: foo\n"))
         job = self.makeRequestBuildsJob(["mips64el", "riscv64"])
+        self.assertEqual(
+            get_transaction_timestamp(IStore(job.snap)), job.date_created)
+        transaction.commit()
         with person_logged_in(job.requester):
             builds = job.snap.requestBuildsFromJob(
                 job.requester, job.archive, job.pocket,
@@ -460,6 +476,9 @@
             repository_url="https://example.com/foo.git";)
         job = self.makeRequestBuildsJob(
             ["mips64el", "riscv64"], git_ref=git_ref)
+        self.assertEqual(
+            get_transaction_timestamp(IStore(job.snap)), job.date_created)
+        transaction.commit()
         with person_logged_in(job.requester):
             builds = job.snap.requestBuildsFromJob(
                 job.requester, job.archive, job.pocket,
@@ -2552,6 +2571,7 @@
         [git_ref] = self.factory.makeGitRefs()
         snap = self.makeSnap(
             git_ref=git_ref, distroseries=distroseries, processors=processors)
+        now = get_transaction_timestamp(IStore(distroseries))
         response = self.webservice.named_post(
             snap["self_link"], "requestBuilds", archive=archive_url,
             pocket="Updates", channels={"snapcraft": "edge"})
@@ -2559,6 +2579,9 @@
         build_request_url = response.getHeader("Location")
         build_request = self.webservice.get(build_request_url).jsonBody()
         self.assertThat(build_request, ContainsDict({
+            "date_requested": AfterPreprocessing(
+                iso8601.parse_date, GreaterThan(now)),
+            "date_finished": Is(None),
             "snap_link": Equals(snap["self_link"]),
             "status": Equals("Pending"),
             "error_message": Is(None),
@@ -2573,9 +2596,16 @@
             [job] = getUtility(ISnapRequestBuildsJobSource).iterReady()
             with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
                 JobRunner([job]).runAll()
+        date_requested = iso8601.parse_date(build_request["date_requested"])
+        now = get_transaction_timestamp(IStore(distroseries))
         build_request = self.webservice.get(
             build_request["self_link"]).jsonBody()
         self.assertThat(build_request, ContainsDict({
+            "date_requested": AfterPreprocessing(
+                iso8601.parse_date, Equals(date_requested)),
+            "date_finished": AfterPreprocessing(
+                iso8601.parse_date,
+                MatchesAll(GreaterThan(date_requested), LessThan(now))),
             "snap_link": Equals(snap["self_link"]),
             "status": Equals("Completed"),
             "error_message": Is(None),
@@ -2608,6 +2638,7 @@
         snap = self.makeSnap(
             git_ref=git_ref, distroseries=distroseries,
             processors=[processor])
+        now = get_transaction_timestamp(IStore(distroseries))
         response = self.webservice.named_post(
             snap["self_link"], "requestBuilds", archive=archive_url,
             pocket="Updates")
@@ -2615,6 +2646,9 @@
         build_request_url = response.getHeader("Location")
         build_request = self.webservice.get(build_request_url).jsonBody()
         self.assertThat(build_request, ContainsDict({
+            "date_requested": AfterPreprocessing(
+                iso8601.parse_date, GreaterThan(now)),
+            "date_finished": Is(None),
             "snap_link": Equals(snap["self_link"]),
             "status": Equals("Pending"),
             "error_message": Is(None),
@@ -2627,9 +2661,16 @@
             [job] = getUtility(ISnapRequestBuildsJobSource).iterReady()
             with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
                 JobRunner([job]).runAll()
+        date_requested = iso8601.parse_date(build_request["date_requested"])
+        now = get_transaction_timestamp(IStore(distroseries))
         build_request = self.webservice.get(
             build_request["self_link"]).jsonBody()
         self.assertThat(build_request, ContainsDict({
+            "date_requested": AfterPreprocessing(
+                iso8601.parse_date, Equals(date_requested)),
+            "date_finished": AfterPreprocessing(
+                iso8601.parse_date,
+                MatchesAll(GreaterThan(date_requested), LessThan(now))),
             "snap_link": Equals(snap["self_link"]),
             "status": Equals("Failed"),
             "error_message": Equals("Something went wrong"),

=== modified file 'lib/lp/snappy/tests/test_snapjob.py'
--- lib/lp/snappy/tests/test_snapjob.py	2018-06-15 12:54:27 +0000
+++ lib/lp/snappy/tests/test_snapjob.py	2018-08-06 15:25:54 +0000
@@ -13,7 +13,10 @@
     AfterPreprocessing,
     ContainsDict,
     Equals,
+    GreaterThan,
     Is,
+    LessThan,
+    MatchesAll,
     MatchesSetwise,
     MatchesStructure,
     )
@@ -21,6 +24,8 @@
 from lp.code.tests.helpers import GitHostingFixture
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.config import config
+from lp.services.database.interfaces import IStore
+from lp.services.database.sqlbase import get_transaction_timestamp
 from lp.services.job.interfaces.job import JobStatus
 from lp.services.job.runner import JobRunner
 from lp.services.mail.sendmail import format_address_for_person
@@ -97,6 +102,7 @@
         [git_ref] = self.factory.makeGitRefs()
         snap = self.factory.makeSnap(
             git_ref=git_ref, distroseries=distroseries, processors=processors)
+        expected_date_created = get_transaction_timestamp(IStore(snap))
         job = SnapRequestBuildsJob.create(
             snap, snap.registrant, distroseries.main_archive,
             PackagePublishingPocket.RELEASE, {"core": "stable"})
@@ -108,9 +114,13 @@
         self.useFixture(GitHostingFixture(blob=snapcraft_yaml))
         with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
             JobRunner([job]).runAll()
+        now = get_transaction_timestamp(IStore(snap))
         self.assertEmailQueueLength(0)
         self.assertThat(job, MatchesStructure(
             job=MatchesStructure.byEquality(status=JobStatus.COMPLETED),
+            date_created=Equals(expected_date_created),
+            date_finished=MatchesAll(
+                GreaterThan(expected_date_created), LessThan(now)),
             error_message=Is(None),
             builds=AfterPreprocessing(set, MatchesSetwise(*[
                 MatchesStructure.byEquality(
@@ -131,6 +141,7 @@
         [git_ref] = self.factory.makeGitRefs()
         snap = self.factory.makeSnap(
             git_ref=git_ref, distroseries=distroseries, processors=processors)
+        expected_date_created = get_transaction_timestamp(IStore(snap))
         job = SnapRequestBuildsJob.create(
             snap, snap.registrant, distroseries.main_archive,
             PackagePublishingPocket.RELEASE, {"core": "stable"})
@@ -138,6 +149,7 @@
             CannotParseSnapcraftYaml("Nonsense on stilts"))
         with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
             JobRunner([job]).runAll()
+        now = get_transaction_timestamp(IStore(snap))
         [notification] = self.assertEmailQueueLength(1)
         self.assertThat(dict(notification), ContainsDict({
             "From": Equals(config.canonical.noreply_from_address),
@@ -151,5 +163,8 @@
             notification.get_payload(decode=True))
         self.assertThat(job, MatchesStructure(
             job=MatchesStructure.byEquality(status=JobStatus.FAILED),
+            date_created=Equals(expected_date_created),
+            date_finished=MatchesAll(
+                GreaterThan(expected_date_created), LessThan(now)),
             error_message=Equals("Nonsense on stilts"),
             builds=AfterPreprocessing(set, MatchesSetwise())))


Follow ups