Merge lp:~cjwatson/launchpad/snap-build-channels into lp:launchpad
- snap-build-channels
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 18579 |
Proposed branch: | lp:~cjwatson/launchpad/snap-build-channels |
Merge into: | lp:launchpad |
Diff against target: |
512 lines (+177/-25) 9 files modified
lib/lp/snappy/interfaces/snap.py (+22/-3) lib/lp/snappy/interfaces/snapbuild.py (+9/-1) lib/lp/snappy/model/snap.py (+22/-10) lib/lp/snappy/model/snapbuild.py (+7/-3) lib/lp/snappy/model/snapbuildbehaviour.py (+3/-1) lib/lp/snappy/tests/test_snap.py (+93/-1) lib/lp/snappy/tests/test_snapbuild.py (+1/-0) lib/lp/snappy/tests/test_snapbuildbehaviour.py (+12/-1) lib/lp/testing/factory.py (+8/-5) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/snap-build-channels |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+337360@code.launchpad.net |
Commit message
Add the ability to select source channels when building snaps.
Description of the change
This will let us run snap builds where snapcraft is installed as a snap. It depends on https:/
We'll probably also want a feature flag to change the default, but that can be added a little later, once the basic mechanism works.
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Revision history for this message
Colin Watson (cjwatson) : | # |
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 2017-08-22 11:36:30 +0000 |
3 | +++ lib/lp/snappy/interfaces/snap.py 2018-03-22 16:49:25 +0000 |
4 | @@ -1,4 +1,4 @@ |
5 | -# Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
6 | +# Copyright 2015-2018 Canonical Ltd. This software is licensed under the |
7 | # GNU Affero General Public License version 3 (see the file LICENSE). |
8 | |
9 | """Snap package interfaces.""" |
10 | @@ -63,6 +63,7 @@ |
11 | Bool, |
12 | Choice, |
13 | Datetime, |
14 | + Dict, |
15 | Int, |
16 | List, |
17 | Text, |
18 | @@ -281,17 +282,27 @@ |
19 | @operation_parameters( |
20 | archive=Reference(schema=IArchive), |
21 | distro_arch_series=Reference(schema=IDistroArchSeries), |
22 | - pocket=Choice(vocabulary=PackagePublishingPocket)) |
23 | + pocket=Choice(vocabulary=PackagePublishingPocket), |
24 | + channels=Dict( |
25 | + title=_("Source snap channels to use for this build."), |
26 | + description=_( |
27 | + "A dictionary mapping snap names to channels to use for this " |
28 | + "build. Currently only 'core' and 'snapcraft' keys are " |
29 | + "supported."), |
30 | + key_type=TextLine(), required=False)) |
31 | # Really ISnapBuild, patched in lp.snappy.interfaces.webservice. |
32 | @export_factory_operation(Interface, []) |
33 | @operation_for_version("devel") |
34 | - def requestBuild(requester, archive, distro_arch_series, pocket): |
35 | + def requestBuild(requester, archive, distro_arch_series, pocket, |
36 | + channels=None): |
37 | """Request that the snap package be built. |
38 | |
39 | :param requester: The person requesting the build. |
40 | :param archive: The IArchive to associate the build with. |
41 | :param distro_arch_series: The architecture to build for. |
42 | :param pocket: The pocket that should be targeted. |
43 | + :param channels: A dictionary mapping snap names to channels to use |
44 | + for this build. |
45 | :return: `ISnapBuild`. |
46 | """ |
47 | |
48 | @@ -509,6 +520,14 @@ |
49 | "The package stream within the source distribution series to use " |
50 | "when building the snap package."))) |
51 | |
52 | + auto_build_channels = exported(Dict( |
53 | + title=_("Source snap channels for automatic builds"), |
54 | + key_type=TextLine(), required=False, readonly=False, |
55 | + description=_( |
56 | + "A dictionary mapping snap names to channels to use when building " |
57 | + "this snap package. Currently only 'core' and 'snapcraft' keys " |
58 | + "are supported."))) |
59 | + |
60 | is_stale = Bool( |
61 | title=_("Snap package is stale and is due to be rebuilt."), |
62 | required=True, readonly=False) |
63 | |
64 | === modified file 'lib/lp/snappy/interfaces/snapbuild.py' |
65 | --- lib/lp/snappy/interfaces/snapbuild.py 2018-02-16 21:48:03 +0000 |
66 | +++ lib/lp/snappy/interfaces/snapbuild.py 2018-03-22 16:49:25 +0000 |
67 | @@ -1,4 +1,4 @@ |
68 | -# Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
69 | +# Copyright 2015-2018 Canonical Ltd. This software is licensed under the |
70 | # GNU Affero General Public License version 3 (see the file LICENSE). |
71 | |
72 | """Snap package build interfaces.""" |
73 | @@ -149,6 +149,14 @@ |
74 | title=_("The pocket for which to build."), |
75 | vocabulary=PackagePublishingPocket, required=True, readonly=True)) |
76 | |
77 | + channels = exported(Dict( |
78 | + title=_("Source snap channels to use for this build."), |
79 | + description=_( |
80 | + "A dictionary mapping snap names to channels to use for this " |
81 | + "build. Currently only 'core' and 'snapcraft' keys are " |
82 | + "supported."), |
83 | + key_type=TextLine())) |
84 | + |
85 | virtualized = Bool( |
86 | title=_("If True, this build is virtualized."), readonly=True) |
87 | |
88 | |
89 | === modified file 'lib/lp/snappy/model/snap.py' |
90 | --- lib/lp/snappy/model/snap.py 2017-11-10 11:23:27 +0000 |
91 | +++ lib/lp/snappy/model/snap.py 2018-03-22 16:49:25 +0000 |
92 | @@ -1,4 +1,4 @@ |
93 | -# Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
94 | +# Copyright 2015-2018 Canonical Ltd. This software is licensed under the |
95 | # GNU Affero General Public License version 3 (see the file LICENSE). |
96 | |
97 | __metaclass__ = type |
98 | @@ -94,6 +94,7 @@ |
99 | ) |
100 | from lp.services.database.stormexpr import ( |
101 | Greatest, |
102 | + IsDistinctFrom, |
103 | NullsLast, |
104 | ) |
105 | from lp.services.features import getFeatureFlag |
106 | @@ -189,6 +190,8 @@ |
107 | |
108 | auto_build_pocket = DBEnum(enum=PackagePublishingPocket, allow_none=True) |
109 | |
110 | + auto_build_channels = JSON('auto_build_channels', allow_none=True) |
111 | + |
112 | is_stale = Bool(name='is_stale', allow_none=False) |
113 | |
114 | require_virtualized = Bool(name='require_virtualized') |
115 | @@ -209,9 +212,10 @@ |
116 | def __init__(self, registrant, owner, distro_series, name, |
117 | description=None, branch=None, git_ref=None, auto_build=False, |
118 | auto_build_archive=None, auto_build_pocket=None, |
119 | - require_virtualized=True, date_created=DEFAULT, |
120 | - private=False, store_upload=False, store_series=None, |
121 | - store_name=None, store_secrets=None, store_channels=None): |
122 | + auto_build_channels=None, require_virtualized=True, |
123 | + date_created=DEFAULT, private=False, store_upload=False, |
124 | + store_series=None, store_name=None, store_secrets=None, |
125 | + store_channels=None): |
126 | """Construct a `Snap`.""" |
127 | super(Snap, self).__init__() |
128 | self.registrant = registrant |
129 | @@ -224,6 +228,7 @@ |
130 | self.auto_build = auto_build |
131 | self.auto_build_archive = auto_build_archive |
132 | self.auto_build_pocket = auto_build_pocket |
133 | + self.auto_build_channels = auto_build_channels |
134 | self.require_virtualized = require_virtualized |
135 | self.date_created = date_created |
136 | self.date_last_modified = date_created |
137 | @@ -439,7 +444,8 @@ |
138 | return False |
139 | return True |
140 | |
141 | - def requestBuild(self, requester, archive, distro_arch_series, pocket): |
142 | + def requestBuild(self, requester, archive, distro_arch_series, pocket, |
143 | + channels=None): |
144 | """See `ISnap`.""" |
145 | if not requester.inTeam(self.owner): |
146 | raise SnapNotOwner( |
147 | @@ -459,12 +465,14 @@ |
148 | SnapBuild.archive_id == archive.id, |
149 | SnapBuild.distro_arch_series_id == distro_arch_series.id, |
150 | SnapBuild.pocket == pocket, |
151 | + SnapBuild.channels == channels, |
152 | SnapBuild.status == BuildStatus.NEEDSBUILD) |
153 | if pending.any() is not None: |
154 | raise SnapBuildAlreadyPending |
155 | |
156 | build = getUtility(ISnapBuildSet).new( |
157 | - requester, self, archive, distro_arch_series, pocket) |
158 | + requester, self, archive, distro_arch_series, pocket, |
159 | + channels=channels) |
160 | build.queueBuild() |
161 | return build |
162 | |
163 | @@ -484,7 +492,7 @@ |
164 | try: |
165 | build = self.requestBuild( |
166 | self.owner, self.auto_build_archive, arch, |
167 | - self.auto_build_pocket) |
168 | + self.auto_build_pocket, self.auto_build_channels) |
169 | if logger is not None: |
170 | logger.debug( |
171 | " - %s/%s/%s: Build requested.", |
172 | @@ -659,9 +667,10 @@ |
173 | branch=None, git_repository=None, git_repository_url=None, |
174 | git_path=None, git_ref=None, auto_build=False, |
175 | auto_build_archive=None, auto_build_pocket=None, |
176 | - require_virtualized=True, processors=None, date_created=DEFAULT, |
177 | - private=False, store_upload=False, store_series=None, |
178 | - store_name=None, store_secrets=None, store_channels=None): |
179 | + auto_build_channels=None, require_virtualized=True, |
180 | + processors=None, date_created=DEFAULT, private=False, |
181 | + store_upload=False, store_series=None, store_name=None, |
182 | + store_secrets=None, store_channels=None): |
183 | """See `ISnapSet`.""" |
184 | if not registrant.inTeam(owner): |
185 | if owner.is_team: |
186 | @@ -702,6 +711,7 @@ |
187 | branch=branch, git_ref=git_ref, auto_build=auto_build, |
188 | auto_build_archive=auto_build_archive, |
189 | auto_build_pocket=auto_build_pocket, |
190 | + auto_build_channels=auto_build_channels, |
191 | require_virtualized=require_virtualized, date_created=date_created, |
192 | private=private, store_upload=store_upload, |
193 | store_series=store_series, store_name=store_name, |
194 | @@ -917,6 +927,8 @@ |
195 | SnapBuild.snap_id == Snap.id, |
196 | SnapBuild.archive_id == Snap.auto_build_archive_id, |
197 | SnapBuild.pocket == Snap.auto_build_pocket, |
198 | + Not(IsDistinctFrom( |
199 | + SnapBuild.channels, Snap.auto_build_channels)), |
200 | # We only want Snaps that haven't had an automatic |
201 | # SnapBuild dispatched for them recently. |
202 | SnapBuild.date_created >= threshold_date)), |
203 | |
204 | === modified file 'lib/lp/snappy/model/snapbuild.py' |
205 | --- lib/lp/snappy/model/snapbuild.py 2018-02-16 21:48:03 +0000 |
206 | +++ lib/lp/snappy/model/snapbuild.py 2018-03-22 16:49:25 +0000 |
207 | @@ -22,6 +22,7 @@ |
208 | DateTime, |
209 | Desc, |
210 | Int, |
211 | + JSON, |
212 | Reference, |
213 | Select, |
214 | SQL, |
215 | @@ -142,6 +143,8 @@ |
216 | |
217 | pocket = DBEnum(enum=PackagePublishingPocket, allow_none=False) |
218 | |
219 | + channels = JSON('channels', allow_none=True) |
220 | + |
221 | processor_id = Int(name='processor', allow_none=False) |
222 | processor = Reference(processor_id, 'Processor.id') |
223 | virtualized = Bool(name='virtualized') |
224 | @@ -171,7 +174,7 @@ |
225 | failure_count = Int(name='failure_count', allow_none=False) |
226 | |
227 | def __init__(self, build_farm_job, requester, snap, archive, |
228 | - distro_arch_series, pocket, processor, virtualized, |
229 | + distro_arch_series, pocket, channels, processor, virtualized, |
230 | date_created): |
231 | """Construct a `SnapBuild`.""" |
232 | super(SnapBuild, self).__init__() |
233 | @@ -181,6 +184,7 @@ |
234 | self.archive = archive |
235 | self.distro_arch_series = distro_arch_series |
236 | self.pocket = pocket |
237 | + self.channels = channels |
238 | self.processor = processor |
239 | self.virtualized = virtualized |
240 | self.date_created = date_created |
241 | @@ -484,7 +488,7 @@ |
242 | class SnapBuildSet(SpecificBuildFarmJobSourceMixin): |
243 | |
244 | def new(self, requester, snap, archive, distro_arch_series, pocket, |
245 | - date_created=DEFAULT): |
246 | + channels=None, date_created=DEFAULT): |
247 | """See `ISnapBuildSet`.""" |
248 | store = IMasterStore(SnapBuild) |
249 | build_farm_job = getUtility(IBuildFarmJobSource).new( |
250 | @@ -492,7 +496,7 @@ |
251 | archive) |
252 | snapbuild = SnapBuild( |
253 | build_farm_job, requester, snap, archive, distro_arch_series, |
254 | - pocket, distro_arch_series.processor, |
255 | + pocket, channels, distro_arch_series.processor, |
256 | not distro_arch_series.processor.supports_nonvirtualized |
257 | or snap.require_virtualized or archive.require_virtualized, |
258 | date_created) |
259 | |
260 | === modified file 'lib/lp/snappy/model/snapbuildbehaviour.py' |
261 | --- lib/lp/snappy/model/snapbuildbehaviour.py 2018-03-01 17:36:31 +0000 |
262 | +++ lib/lp/snappy/model/snapbuildbehaviour.py 2018-03-22 16:49:25 +0000 |
263 | @@ -1,4 +1,4 @@ |
264 | -# Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
265 | +# Copyright 2015-2018 Canonical Ltd. This software is licensed under the |
266 | # GNU Affero General Public License version 3 (see the file LICENSE). |
267 | |
268 | """An `IBuildFarmJobBehaviour` for `SnapBuild`. |
269 | @@ -109,6 +109,8 @@ |
270 | logger=logger)) |
271 | args["archive_private"] = build.archive.private |
272 | args["build_url"] = canonical_url(build) |
273 | + if build.channels is not None: |
274 | + args["channels"] = build.channels |
275 | if build.snap.branch is not None: |
276 | args["branch"] = build.snap.branch.bzr_identity |
277 | elif build.snap.git_ref is not None: |
278 | |
279 | === modified file 'lib/lp/snappy/tests/test_snap.py' |
280 | --- lib/lp/snappy/tests/test_snap.py 2018-01-23 18:54:30 +0000 |
281 | +++ lib/lp/snappy/tests/test_snap.py 2018-03-22 16:49:25 +0000 |
282 | @@ -54,6 +54,7 @@ |
283 | ONE_DAY_AGO, |
284 | UTC_NOW, |
285 | ) |
286 | +from lp.services.database.interfaces import IStore |
287 | from lp.services.database.sqlbase import flush_database_caches |
288 | from lp.services.features.testing import ( |
289 | FeatureFixture, |
290 | @@ -188,6 +189,7 @@ |
291 | self.assertEqual(snap.distro_series.main_archive, build.archive) |
292 | self.assertEqual(distroarchseries, build.distro_arch_series) |
293 | self.assertEqual(PackagePublishingPocket.UPDATES, build.pocket) |
294 | + self.assertIsNone(build.channels) |
295 | self.assertEqual(BuildStatus.NEEDSBUILD, build.status) |
296 | store = Store.of(build) |
297 | store.flush() |
298 | @@ -232,6 +234,18 @@ |
299 | queue_record.score() |
300 | self.assertEqual(2610, queue_record.lastscore) |
301 | |
302 | + def test_requestBuild_channels(self): |
303 | + # requestBuild can select non-default channels. |
304 | + processor = self.factory.makeProcessor(supports_virtualized=True) |
305 | + distroarchseries = self.makeBuildableDistroArchSeries( |
306 | + processor=processor) |
307 | + snap = self.factory.makeSnap( |
308 | + distroseries=distroarchseries.distroseries, processors=[processor]) |
309 | + build = snap.requestBuild( |
310 | + snap.owner, snap.distro_series.main_archive, distroarchseries, |
311 | + PackagePublishingPocket.UPDATES, channels={"snapcraft": "edge"}) |
312 | + self.assertEqual({"snapcraft": "edge"}, build.channels) |
313 | + |
314 | def test_requestBuild_rejects_repeats(self): |
315 | # requestBuild refuses if there is already a pending build. |
316 | distroseries = self.factory.makeDistroSeries() |
317 | @@ -355,10 +369,36 @@ |
318 | with person_logged_in(snap.owner): |
319 | builds = snap.requestAutoBuilds() |
320 | self.assertThat(builds, MatchesSetwise( |
321 | + *(MatchesStructure( |
322 | + requester=Equals(snap.owner), snap=Equals(snap), |
323 | + archive=Equals(archive), distro_arch_series=Equals(das), |
324 | + pocket=Equals(PackagePublishingPocket.PROPOSED), |
325 | + channels=Is(None)) |
326 | + for das in dases[:2]))) |
327 | + |
328 | + def test_requestAutoBuilds_channels(self): |
329 | + # requestAutoBuilds honours Snap.auto_build_channels. |
330 | + distroseries = self.factory.makeDistroSeries() |
331 | + dases = [] |
332 | + for _ in range(3): |
333 | + processor = self.factory.makeProcessor(supports_virtualized=True) |
334 | + dases.append(self.makeBuildableDistroArchSeries( |
335 | + distroseries=distroseries, processor=processor)) |
336 | + archive = self.factory.makeArchive() |
337 | + snap = self.factory.makeSnap( |
338 | + distroseries=distroseries, |
339 | + processors=[das.processor for das in dases[:2]], |
340 | + auto_build_archive=archive, |
341 | + auto_build_pocket=PackagePublishingPocket.PROPOSED, |
342 | + auto_build_channels={"snapcraft": "edge"}) |
343 | + with person_logged_in(snap.owner): |
344 | + builds = snap.requestAutoBuilds() |
345 | + self.assertThat(builds, MatchesSetwise( |
346 | *(MatchesStructure.byEquality( |
347 | requester=snap.owner, snap=snap, archive=archive, |
348 | distro_arch_series=das, |
349 | - pocket=PackagePublishingPocket.PROPOSED) |
350 | + pocket=PackagePublishingPocket.PROPOSED, |
351 | + channels={"snapcraft": "edge"}) |
352 | for das in dases[:2]))) |
353 | |
354 | def test_getBuilds(self): |
355 | @@ -610,6 +650,7 @@ |
356 | self.assertFalse(snap.auto_build) |
357 | self.assertIsNone(snap.auto_build_archive) |
358 | self.assertIsNone(snap.auto_build_pocket) |
359 | + self.assertIsNone(snap.auto_build_channels) |
360 | self.assertTrue(snap.require_virtualized) |
361 | self.assertFalse(snap.private) |
362 | |
363 | @@ -630,6 +671,7 @@ |
364 | self.assertFalse(snap.auto_build) |
365 | self.assertIsNone(snap.auto_build_archive) |
366 | self.assertIsNone(snap.auto_build_pocket) |
367 | + self.assertIsNone(snap.auto_build_channels) |
368 | self.assertTrue(snap.require_virtualized) |
369 | self.assertFalse(snap.private) |
370 | |
371 | @@ -1008,6 +1050,56 @@ |
372 | self.assertEqual([], builds) |
373 | self.assertEqual([], logger.getLogBuffer().splitlines()) |
374 | |
375 | + def test_makeAutoBuilds_skips_if_built_recently_matching_channels(self): |
376 | + # ISnapSet.makeAutoBuilds only considers recently-requested builds |
377 | + # to match a snap if they match its auto_build_channels. |
378 | + das1, snap1 = self.makeAutoBuildableSnap(is_stale=True) |
379 | + das2, snap2 = self.makeAutoBuildableSnap( |
380 | + is_stale=True, auto_build_channels={"snapcraft": "edge"}) |
381 | + # Create some builds with mismatched channels. |
382 | + self.factory.makeSnapBuild( |
383 | + requester=snap1.owner, snap=snap1, |
384 | + archive=snap1.auto_build_archive, distroarchseries=das1, |
385 | + channels={"snapcraft": "edge"}) |
386 | + self.factory.makeSnapBuild( |
387 | + requester=snap2.owner, snap=snap2, |
388 | + archive=snap2.auto_build_archive, distroarchseries=das2, |
389 | + channels={"snapcraft": "stable"}) |
390 | + |
391 | + logger = BufferLogger() |
392 | + builds = getUtility(ISnapSet).makeAutoBuilds(logger=logger) |
393 | + self.assertThat(builds, MatchesSetwise( |
394 | + MatchesStructure( |
395 | + requester=Equals(snap1.owner), snap=Equals(snap1), |
396 | + distro_arch_series=Equals(das1), channels=Is(None), |
397 | + status=Equals(BuildStatus.NEEDSBUILD)), |
398 | + MatchesStructure.byEquality( |
399 | + requester=snap2.owner, snap=snap2, distro_arch_series=das2, |
400 | + channels={"snapcraft": "edge"}, status=BuildStatus.NEEDSBUILD), |
401 | + )) |
402 | + log_entries = logger.getLogBuffer().splitlines() |
403 | + self.assertEqual(4, len(log_entries)) |
404 | + for das, snap in (das1, snap1), (das2, snap2): |
405 | + self.assertIn( |
406 | + "DEBUG Scheduling builds of snap package %s/%s" % ( |
407 | + snap.owner.name, snap.name), |
408 | + log_entries) |
409 | + self.assertIn( |
410 | + "DEBUG - %s/%s/%s: Build requested." % ( |
411 | + snap.owner.name, snap.name, das.architecturetag), |
412 | + log_entries) |
413 | + self.assertFalse(snap.is_stale) |
414 | + |
415 | + # Mark the two snaps stale and try again. There are now matching |
416 | + # builds so we don't try to request more. |
417 | + for snap in snap1, snap2: |
418 | + removeSecurityProxy(snap).is_stale = True |
419 | + IStore(snap).flush() |
420 | + logger = BufferLogger() |
421 | + builds = getUtility(ISnapSet).makeAutoBuilds(logger=logger) |
422 | + self.assertEqual([], builds) |
423 | + self.assertEqual([], logger.getLogBuffer().splitlines()) |
424 | + |
425 | def test_makeAutoBuilds_skips_non_stale_snaps(self): |
426 | # ISnapSet.makeAutoBuilds skips snap packages that are not stale. |
427 | das, snap = self.makeAutoBuildableSnap(is_stale=False) |
428 | |
429 | === modified file 'lib/lp/snappy/tests/test_snapbuild.py' |
430 | --- lib/lp/snappy/tests/test_snapbuild.py 2018-01-23 10:59:44 +0000 |
431 | +++ lib/lp/snappy/tests/test_snapbuild.py 2018-03-22 16:49:25 +0000 |
432 | @@ -597,6 +597,7 @@ |
433 | self.assertEqual( |
434 | db_build.distro_arch_series.architecturetag, build["arch_tag"]) |
435 | self.assertEqual("Updates", build["pocket"]) |
436 | + self.assertIsNone(build["channels"]) |
437 | self.assertIsNone(build["score"]) |
438 | self.assertFalse(build["can_be_rescored"]) |
439 | self.assertFalse(build["can_be_cancelled"]) |
440 | |
441 | === modified file 'lib/lp/snappy/tests/test_snapbuildbehaviour.py' |
442 | --- lib/lp/snappy/tests/test_snapbuildbehaviour.py 2018-03-01 17:36:31 +0000 |
443 | +++ lib/lp/snappy/tests/test_snapbuildbehaviour.py 2018-03-22 16:49:25 +0000 |
444 | @@ -1,4 +1,4 @@ |
445 | -# Copyright 2015-2017 Canonical Ltd. This software is licensed under the |
446 | +# Copyright 2015-2018 Canonical Ltd. This software is licensed under the |
447 | # GNU Affero General Public License version 3 (see the file LICENSE). |
448 | |
449 | """Test snap package build behaviour.""" |
450 | @@ -402,6 +402,17 @@ |
451 | ])) |
452 | |
453 | @defer.inlineCallbacks |
454 | + def test_extraBuildArgs_channels(self): |
455 | + # If the build needs particular channels, _extraBuildArgs sends |
456 | + # them. |
457 | + job = self.makeJob(channels={"snapcraft": "edge"}) |
458 | + expected_archives, expected_trusted_keys = ( |
459 | + yield get_sources_list_for_building( |
460 | + job.build, job.build.distro_arch_series, None)) |
461 | + args = yield job._extraBuildArgs() |
462 | + self.assertEqual({"snapcraft": "edge"}, args["channels"]) |
463 | + |
464 | + @defer.inlineCallbacks |
465 | def test_composeBuildRequest_proxy_url_set(self): |
466 | job = self.makeJob() |
467 | build_request = yield job.composeBuildRequest(None) |
468 | |
469 | === modified file 'lib/lp/testing/factory.py' |
470 | --- lib/lp/testing/factory.py 2018-02-24 09:11:39 +0000 |
471 | +++ lib/lp/testing/factory.py 2018-03-22 16:49:25 +0000 |
472 | @@ -4670,7 +4670,8 @@ |
473 | def makeSnap(self, registrant=None, owner=None, distroseries=None, |
474 | name=None, branch=None, git_ref=None, auto_build=False, |
475 | auto_build_archive=None, auto_build_pocket=None, |
476 | - is_stale=None, require_virtualized=True, processors=None, |
477 | + auto_build_channels=None, is_stale=None, |
478 | + require_virtualized=True, processors=None, |
479 | date_created=DEFAULT, private=False, store_upload=False, |
480 | store_series=None, store_name=None, store_secrets=None, |
481 | store_channels=None): |
482 | @@ -4696,7 +4697,8 @@ |
483 | require_virtualized=require_virtualized, processors=processors, |
484 | date_created=date_created, branch=branch, git_ref=git_ref, |
485 | auto_build=auto_build, auto_build_archive=auto_build_archive, |
486 | - auto_build_pocket=auto_build_pocket, private=private, |
487 | + auto_build_pocket=auto_build_pocket, |
488 | + auto_build_channels=auto_build_channels, private=private, |
489 | store_upload=store_upload, store_series=store_series, |
490 | store_name=store_name, store_secrets=store_secrets, |
491 | store_channels=store_channels) |
492 | @@ -4707,8 +4709,9 @@ |
493 | |
494 | def makeSnapBuild(self, requester=None, registrant=None, snap=None, |
495 | archive=None, distroarchseries=None, pocket=None, |
496 | - date_created=DEFAULT, status=BuildStatus.NEEDSBUILD, |
497 | - builder=None, duration=None, **kwargs): |
498 | + channels=None, date_created=DEFAULT, |
499 | + status=BuildStatus.NEEDSBUILD, builder=None, |
500 | + duration=None, **kwargs): |
501 | """Make a new SnapBuild.""" |
502 | if requester is None: |
503 | requester = self.makePerson() |
504 | @@ -4736,7 +4739,7 @@ |
505 | pocket = PackagePublishingPocket.UPDATES |
506 | snapbuild = getUtility(ISnapBuildSet).new( |
507 | requester, snap, archive, distroarchseries, pocket, |
508 | - date_created=date_created) |
509 | + channels=channels, date_created=date_created) |
510 | if duration is not None: |
511 | removeSecurityProxy(snapbuild).updateStatus( |
512 | BuildStatus.BUILDING, builder=builder, |