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

Proposed by Colin Watson on 2018-08-06
Status: Merged
Merged at revision: 18746
Proposed branch: lp:~cjwatson/launchpad/snap-build-request-date-attrs
Merge into: lp:launchpad
Diff against target: 309 lines (+94/-1)
6 files modified
lib/lp/snappy/interfaces/snap.py (+8/-0)
lib/lp/snappy/interfaces/snapjob.py (+9/-0)
lib/lp/snappy/model/snap.py (+10/-0)
lib/lp/snappy/model/snapjob.py (+10/-0)
lib/lp/snappy/tests/test_snap.py (+42/-1)
lib/lp/snappy/tests/test_snapjob.py (+15/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/snap-build-request-date-attrs
Reviewer Review Type Date Requested Status
William Grant code 2018-08-06 Approve on 2018-08-07
Review via email: mp+352468@code.launchpad.net

Commit message

Add and export SnapBuildRequest.date_requested and SnapBuildRequest.date_finished.

Description of the change

This will let build.snapcraft.io intersperse these appropriately with builds.

To post a comment you must log in.
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/snappy/interfaces/snap.py'
2--- lib/lp/snappy/interfaces/snap.py 2018-06-18 22:08:58 +0000
3+++ lib/lp/snappy/interfaces/snap.py 2018-08-06 15:25:54 +0000
4@@ -289,6 +289,14 @@
5
6 id = Int(title=_("ID"), required=True, readonly=True)
7
8+ date_requested = exported(Datetime(
9+ title=_("The time when this request was made"),
10+ required=True, readonly=True))
11+
12+ date_finished = exported(Datetime(
13+ title=_("The time when this request finished"),
14+ required=False, readonly=True))
15+
16 snap = exported(Reference(
17 # Really ISnap, patched in lp.snappy.interfaces.webservice.
18 Interface,
19
20=== modified file 'lib/lp/snappy/interfaces/snapjob.py'
21--- lib/lp/snappy/interfaces/snapjob.py 2018-06-15 13:21:14 +0000
22+++ lib/lp/snappy/interfaces/snapjob.py 2018-08-06 15:25:54 +0000
23@@ -19,6 +19,7 @@
24 )
25 from zope.schema import (
26 Choice,
27+ Datetime,
28 Dict,
29 List,
30 TextLine,
31@@ -74,6 +75,14 @@
32 "supported."),
33 key_type=TextLine(), required=False, readonly=True)
34
35+ date_created = Datetime(
36+ title=_("Time when this job was created."),
37+ required=True, readonly=True)
38+
39+ date_finished = Datetime(
40+ title=_("Time when this job finished."),
41+ required=True, readonly=True)
42+
43 error_message = TextLine(
44 title=_("Error message resulting from running this job."),
45 required=False, readonly=True)
46
47=== modified file 'lib/lp/snappy/model/snap.py'
48--- lib/lp/snappy/model/snap.py 2018-07-30 09:07:30 +0000
49+++ lib/lp/snappy/model/snap.py 2018-08-06 15:25:54 +0000
50@@ -182,6 +182,16 @@
51 self.id = id
52
53 @property
54+ def date_requested(self):
55+ """See `ISnapBuildRequest`."""
56+ return self._job.date_created
57+
58+ @property
59+ def date_finished(self):
60+ """See `ISnapBuildRequest`."""
61+ return self._job.date_finished
62+
63+ @property
64 def status(self):
65 """See `ISnapBuildRequest`."""
66 status_map = {
67
68=== modified file 'lib/lp/snappy/model/snapjob.py'
69--- lib/lp/snappy/model/snapjob.py 2018-06-15 13:21:14 +0000
70+++ lib/lp/snappy/model/snapjob.py 2018-08-06 15:25:54 +0000
71@@ -233,6 +233,16 @@
72 return self.metadata["channels"]
73
74 @property
75+ def date_created(self):
76+ """See `ISnapRequestBuildsJob`."""
77+ return self.context.job.date_created
78+
79+ @property
80+ def date_finished(self):
81+ """See `ISnapRequestBuildsJob`."""
82+ return self.context.job.date_finished
83+
84+ @property
85 def error_message(self):
86 """See `ISnapRequestBuildsJob`."""
87 return self.metadata.get("error_message")
88
89=== modified file 'lib/lp/snappy/tests/test_snap.py'
90--- lib/lp/snappy/tests/test_snap.py 2018-07-30 09:07:30 +0000
91+++ lib/lp/snappy/tests/test_snap.py 2018-08-06 15:25:54 +0000
92@@ -16,6 +16,7 @@
93 from urlparse import urlsplit
94
95 from fixtures import MockPatch
96+import iso8601
97 from lazr.lifecycle.event import ObjectModifiedEvent
98 from pymacaroons import Macaroon
99 import pytz
100@@ -26,7 +27,10 @@
101 AfterPreprocessing,
102 ContainsDict,
103 Equals,
104+ GreaterThan,
105 Is,
106+ LessThan,
107+ MatchesAll,
108 MatchesDict,
109 MatchesSetwise,
110 MatchesStructure,
111@@ -65,7 +69,10 @@
112 UTC_NOW,
113 )
114 from lp.services.database.interfaces import IStore
115-from lp.services.database.sqlbase import flush_database_caches
116+from lp.services.database.sqlbase import (
117+ flush_database_caches,
118+ get_transaction_timestamp,
119+ )
120 from lp.services.features.testing import (
121 FeatureFixture,
122 MemoryFeatureFixture,
123@@ -372,12 +379,15 @@
124 # requestBuilds schedules a job and returns a corresponding
125 # SnapBuildRequest.
126 snap = self.factory.makeSnap()
127+ now = get_transaction_timestamp(IStore(snap))
128 with person_logged_in(snap.owner.teamowner):
129 request = snap.requestBuilds(
130 snap.owner.teamowner, snap.distro_series.main_archive,
131 PackagePublishingPocket.UPDATES,
132 channels={"snapcraft": "edge"})
133 self.assertThat(request, MatchesStructure(
134+ date_requested=Equals(now),
135+ date_finished=Is(None),
136 snap=Equals(snap),
137 status=Equals(SnapBuildRequestStatus.PENDING),
138 error_message=Is(None),
139@@ -434,6 +444,9 @@
140 - build-on: avr
141 """)))
142 job = self.makeRequestBuildsJob(["sparc"])
143+ self.assertEqual(
144+ get_transaction_timestamp(IStore(job.snap)), job.date_created)
145+ transaction.commit()
146 with person_logged_in(job.requester):
147 builds = job.snap.requestBuildsFromJob(
148 job.requester, job.archive, job.pocket,
149@@ -446,6 +459,9 @@
150 # architectures.
151 self.useFixture(GitHostingFixture(blob="name: foo\n"))
152 job = self.makeRequestBuildsJob(["mips64el", "riscv64"])
153+ self.assertEqual(
154+ get_transaction_timestamp(IStore(job.snap)), job.date_created)
155+ transaction.commit()
156 with person_logged_in(job.requester):
157 builds = job.snap.requestBuildsFromJob(
158 job.requester, job.archive, job.pocket,
159@@ -460,6 +476,9 @@
160 repository_url="https://example.com/foo.git")
161 job = self.makeRequestBuildsJob(
162 ["mips64el", "riscv64"], git_ref=git_ref)
163+ self.assertEqual(
164+ get_transaction_timestamp(IStore(job.snap)), job.date_created)
165+ transaction.commit()
166 with person_logged_in(job.requester):
167 builds = job.snap.requestBuildsFromJob(
168 job.requester, job.archive, job.pocket,
169@@ -2552,6 +2571,7 @@
170 [git_ref] = self.factory.makeGitRefs()
171 snap = self.makeSnap(
172 git_ref=git_ref, distroseries=distroseries, processors=processors)
173+ now = get_transaction_timestamp(IStore(distroseries))
174 response = self.webservice.named_post(
175 snap["self_link"], "requestBuilds", archive=archive_url,
176 pocket="Updates", channels={"snapcraft": "edge"})
177@@ -2559,6 +2579,9 @@
178 build_request_url = response.getHeader("Location")
179 build_request = self.webservice.get(build_request_url).jsonBody()
180 self.assertThat(build_request, ContainsDict({
181+ "date_requested": AfterPreprocessing(
182+ iso8601.parse_date, GreaterThan(now)),
183+ "date_finished": Is(None),
184 "snap_link": Equals(snap["self_link"]),
185 "status": Equals("Pending"),
186 "error_message": Is(None),
187@@ -2573,9 +2596,16 @@
188 [job] = getUtility(ISnapRequestBuildsJobSource).iterReady()
189 with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
190 JobRunner([job]).runAll()
191+ date_requested = iso8601.parse_date(build_request["date_requested"])
192+ now = get_transaction_timestamp(IStore(distroseries))
193 build_request = self.webservice.get(
194 build_request["self_link"]).jsonBody()
195 self.assertThat(build_request, ContainsDict({
196+ "date_requested": AfterPreprocessing(
197+ iso8601.parse_date, Equals(date_requested)),
198+ "date_finished": AfterPreprocessing(
199+ iso8601.parse_date,
200+ MatchesAll(GreaterThan(date_requested), LessThan(now))),
201 "snap_link": Equals(snap["self_link"]),
202 "status": Equals("Completed"),
203 "error_message": Is(None),
204@@ -2608,6 +2638,7 @@
205 snap = self.makeSnap(
206 git_ref=git_ref, distroseries=distroseries,
207 processors=[processor])
208+ now = get_transaction_timestamp(IStore(distroseries))
209 response = self.webservice.named_post(
210 snap["self_link"], "requestBuilds", archive=archive_url,
211 pocket="Updates")
212@@ -2615,6 +2646,9 @@
213 build_request_url = response.getHeader("Location")
214 build_request = self.webservice.get(build_request_url).jsonBody()
215 self.assertThat(build_request, ContainsDict({
216+ "date_requested": AfterPreprocessing(
217+ iso8601.parse_date, GreaterThan(now)),
218+ "date_finished": Is(None),
219 "snap_link": Equals(snap["self_link"]),
220 "status": Equals("Pending"),
221 "error_message": Is(None),
222@@ -2627,9 +2661,16 @@
223 [job] = getUtility(ISnapRequestBuildsJobSource).iterReady()
224 with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
225 JobRunner([job]).runAll()
226+ date_requested = iso8601.parse_date(build_request["date_requested"])
227+ now = get_transaction_timestamp(IStore(distroseries))
228 build_request = self.webservice.get(
229 build_request["self_link"]).jsonBody()
230 self.assertThat(build_request, ContainsDict({
231+ "date_requested": AfterPreprocessing(
232+ iso8601.parse_date, Equals(date_requested)),
233+ "date_finished": AfterPreprocessing(
234+ iso8601.parse_date,
235+ MatchesAll(GreaterThan(date_requested), LessThan(now))),
236 "snap_link": Equals(snap["self_link"]),
237 "status": Equals("Failed"),
238 "error_message": Equals("Something went wrong"),
239
240=== modified file 'lib/lp/snappy/tests/test_snapjob.py'
241--- lib/lp/snappy/tests/test_snapjob.py 2018-06-15 12:54:27 +0000
242+++ lib/lp/snappy/tests/test_snapjob.py 2018-08-06 15:25:54 +0000
243@@ -13,7 +13,10 @@
244 AfterPreprocessing,
245 ContainsDict,
246 Equals,
247+ GreaterThan,
248 Is,
249+ LessThan,
250+ MatchesAll,
251 MatchesSetwise,
252 MatchesStructure,
253 )
254@@ -21,6 +24,8 @@
255 from lp.code.tests.helpers import GitHostingFixture
256 from lp.registry.interfaces.pocket import PackagePublishingPocket
257 from lp.services.config import config
258+from lp.services.database.interfaces import IStore
259+from lp.services.database.sqlbase import get_transaction_timestamp
260 from lp.services.job.interfaces.job import JobStatus
261 from lp.services.job.runner import JobRunner
262 from lp.services.mail.sendmail import format_address_for_person
263@@ -97,6 +102,7 @@
264 [git_ref] = self.factory.makeGitRefs()
265 snap = self.factory.makeSnap(
266 git_ref=git_ref, distroseries=distroseries, processors=processors)
267+ expected_date_created = get_transaction_timestamp(IStore(snap))
268 job = SnapRequestBuildsJob.create(
269 snap, snap.registrant, distroseries.main_archive,
270 PackagePublishingPocket.RELEASE, {"core": "stable"})
271@@ -108,9 +114,13 @@
272 self.useFixture(GitHostingFixture(blob=snapcraft_yaml))
273 with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
274 JobRunner([job]).runAll()
275+ now = get_transaction_timestamp(IStore(snap))
276 self.assertEmailQueueLength(0)
277 self.assertThat(job, MatchesStructure(
278 job=MatchesStructure.byEquality(status=JobStatus.COMPLETED),
279+ date_created=Equals(expected_date_created),
280+ date_finished=MatchesAll(
281+ GreaterThan(expected_date_created), LessThan(now)),
282 error_message=Is(None),
283 builds=AfterPreprocessing(set, MatchesSetwise(*[
284 MatchesStructure.byEquality(
285@@ -131,6 +141,7 @@
286 [git_ref] = self.factory.makeGitRefs()
287 snap = self.factory.makeSnap(
288 git_ref=git_ref, distroseries=distroseries, processors=processors)
289+ expected_date_created = get_transaction_timestamp(IStore(snap))
290 job = SnapRequestBuildsJob.create(
291 snap, snap.registrant, distroseries.main_archive,
292 PackagePublishingPocket.RELEASE, {"core": "stable"})
293@@ -138,6 +149,7 @@
294 CannotParseSnapcraftYaml("Nonsense on stilts"))
295 with dbuser(config.ISnapRequestBuildsJobSource.dbuser):
296 JobRunner([job]).runAll()
297+ now = get_transaction_timestamp(IStore(snap))
298 [notification] = self.assertEmailQueueLength(1)
299 self.assertThat(dict(notification), ContainsDict({
300 "From": Equals(config.canonical.noreply_from_address),
301@@ -151,5 +163,8 @@
302 notification.get_payload(decode=True))
303 self.assertThat(job, MatchesStructure(
304 job=MatchesStructure.byEquality(status=JobStatus.FAILED),
305+ date_created=Equals(expected_date_created),
306+ date_finished=MatchesAll(
307+ GreaterThan(expected_date_created), LessThan(now)),
308 error_message=Equals("Nonsense on stilts"),
309 builds=AfterPreprocessing(set, MatchesSetwise())))