Merge lp:~robru/cupstream2distro/reorg-managers into lp:cupstream2distro
- reorg-managers
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Robert Bruce Park |
Approved revision: | 1131 |
Merged at revision: | 1118 |
Proposed branch: | lp:~robru/cupstream2distro/reorg-managers |
Merge into: | lp:cupstream2distro |
Diff against target: |
1192 lines (+404/-302) 24 files modified
chroot-tools/buildsource-chroot (+0/-1) citrain/abandon.py (+2/-2) citrain/build.py (+32/-89) citrain/merge_clean.py (+2/-11) citrain/migration.py (+3/-3) citrain/publisher.py (+2/-2) citrain/recipes/manager.py (+109/-0) citrain/recipes/merge.py (+1/-0) citrain/revert.py (+4/-3) cupstream2distro/branchhandling.py (+4/-0) cupstream2distro/packagemanager.py (+5/-2) cupstream2distro/utils.py (+1/-11) tests/unit/test_branchhandling.py (+6/-0) tests/unit/test_packagemanager.py (+5/-0) tests/unit/test_recipe_binarysync.py (+2/-1) tests/unit/test_recipe_manager.py (+154/-0) tests/unit/test_recipe_merge.py (+2/-0) tests/unit/test_recipe_secondary.py (+2/-0) tests/unit/test_script_abandon.py (+8/-8) tests/unit/test_script_build.py (+44/-123) tests/unit/test_script_merge_clean.py (+6/-13) tests/unit/test_script_migration.py (+6/-6) tests/unit/test_script_publisher.py (+4/-4) tests/unit/test_utils.py (+0/-23) |
To merge this branch: | bzr merge lp:~robru/cupstream2distro/reorg-managers |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Bruce Park (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+272193@code.launchpad.net |
Commit message
Reorganize BuildManager and MergeManager classes.
Description of the change
Robert Bruce Park (robru) wrote : | # |
Robert Bruce Park (robru) wrote : | # |
I've found a bug in which the vivid build in a dual silo gets confused and watches the wily build a second time during watch phase.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1128
http://
Executed test runs:
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1129
http://
Executed test runs:
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1131
http://
Executed test runs:
Click here to trigger a rebuild:
http://
Robert Bruce Park (robru) wrote : | # |
Ok I've tested this in staging and I'm happy with it, also I'm pleased with the tests, will go live first thing during my shift tomorrow.
Preview Diff
1 | === modified file 'chroot-tools/buildsource-chroot' |
2 | --- chroot-tools/buildsource-chroot 2015-09-23 07:14:54 +0000 |
3 | +++ chroot-tools/buildsource-chroot 2015-09-24 07:13:28 +0000 |
4 | @@ -115,4 +115,3 @@ |
5 | |
6 | $SU "./debian/rules clean" |
7 | $SU "bzr bd -S -- -sa -k$KEY -d -v$DISTRO_VERSION" |
8 | -$SU "bzr revert" |
9 | |
10 | === modified file 'citrain/abandon.py' |
11 | --- citrain/abandon.py 2015-09-22 00:58:14 +0000 |
12 | +++ citrain/abandon.py 2015-09-24 07:13:28 +0000 |
13 | @@ -34,10 +34,10 @@ |
14 | |
15 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) |
16 | |
17 | +from citrain.recipes.manager import Manager |
18 | from cupstream2distro.errors import CITrainError |
19 | from cupstream2distro.utils import env, run_script |
20 | from cupstream2distro.silomanager import SiloState |
21 | -from citrain.merge_clean import MergeManager |
22 | |
23 | |
24 | def main(): |
25 | @@ -51,7 +51,7 @@ |
26 | SiloState.requestid.fget.cache[(silo_state,)] = env.REQUEST_ID |
27 | if silo_state._siloname: |
28 | env.SILONAME = silo_state._siloname |
29 | - MergeManager(silo_state).do('nuke') |
30 | + Manager(silo_state).do('nuke') |
31 | except CITrainError as err: |
32 | logging.error(str(err)) |
33 | finally: |
34 | |
35 | === modified file 'citrain/build.py' |
36 | --- citrain/build.py 2015-09-22 18:51:46 +0000 |
37 | +++ citrain/build.py 2015-09-24 07:13:28 +0000 |
38 | @@ -50,44 +50,31 @@ |
39 | |
40 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) |
41 | |
42 | -from citrain.recipes.base import BuildBase |
43 | -from citrain.recipes.merge import Merge |
44 | -from citrain.recipes.manual import Manual |
45 | -from citrain.recipes.secondary import Secondary |
46 | -from citrain.recipes.sourcesync import SourceSync |
47 | -from citrain.recipes.binarysync import BinarySync |
48 | +from glob import glob |
49 | +from os.path import basename |
50 | + |
51 | +from citrain.recipes.manager import Manager |
52 | from cupstream2distro.silomanager import SiloState |
53 | from cupstream2distro.errors import BuildError, CITrainError |
54 | -from cupstream2distro.utils import ( |
55 | - env, |
56 | - find_all_uploaded, |
57 | - log_value_of, |
58 | - run_script, |
59 | -) |
60 | - |
61 | - |
62 | -class BuildManager(object): |
63 | - """Decide which packages to build, and when.""" |
64 | - |
65 | - def __init__(self, silo_state): |
66 | - self.silo_state = silo_state |
67 | - self.names = set() |
68 | - self.phases = [] |
69 | - self.builds = {} |
70 | - self.types = {} |
71 | - |
72 | - def do(self, *phases): |
73 | - """Perform all specified phases. |
74 | - |
75 | - :param phases: A list of phase name strings. |
76 | - :raises: CITrainError in case anything goes wrong. |
77 | - """ |
78 | - if not self.types: |
79 | - self.choose_packages() |
80 | - self.choose_classes() |
81 | - self.instantiate_build_objects() |
82 | - for phase in phases: |
83 | - self.execute_phase(phase) |
84 | +from cupstream2distro.utils import SILO_DIR, env, run_script |
85 | + |
86 | + |
87 | +def find_all_uploaded(): |
88 | + """Return all source package names and versions uploaded to the ppa. |
89 | + |
90 | + :yields: Source package names that have been uploaded. |
91 | + """ |
92 | + for uploaded in glob(SILO_DIR('*_source.ppa.upload')): |
93 | + yield basename(uploaded).split('_')[0] |
94 | + |
95 | + |
96 | +class BuildManager(Manager): |
97 | + """Honor PACKAGES_TO_REBUILD during building.""" |
98 | + |
99 | + def include_all(self): |
100 | + """Ignore PACKAGES_TO_REBUILD and include all.""" |
101 | + self.choose_packages = super().choose_packages |
102 | + self.types.clear() |
103 | |
104 | def choose_packages(self): |
105 | """Decide which packages need to be built.""" |
106 | @@ -104,68 +91,24 @@ |
107 | if self.names: |
108 | logging.info('Including {}.'.format(', '.join(self.names))) |
109 | else: |
110 | - # Don't bother raising this a second time during diff phase... |
111 | - self.do = lambda *ignore: None |
112 | raise BuildError( |
113 | 'No packages are being considered. You probably want one of ' |
114 | 'PACKAGES_TO_REBUILD, FORCE_REBUILD, or WATCH_ONLY.') |
115 | |
116 | - def choose_classes(self): |
117 | - """Decide which class to use for each individual package build.""" |
118 | - include_binaries = env.INCLUDE_BINARIES_IN_SYNC == 'true' |
119 | - Sync = BinarySync if include_binaries else SourceSync |
120 | - Source = Sync if self.silo_state.source_archive else Manual |
121 | - self.types = { |
122 | - Merge: self.names & set(self.silo_state.mps), |
123 | - Source: self.names & set(self.silo_state.sources), |
124 | - } |
125 | - if self.silo_state.source_archive: |
126 | - Sync.from_archive = self.silo_state.source_archive |
127 | - Sync.from_series = self.silo_state.source_series |
128 | - Merge.all_mps = self.silo_state.mps |
129 | - |
130 | - def instantiate_build_objects(self): |
131 | - """Instantiate the chosen classes for each chosen package.""" |
132 | - series = self.silo_state.series |
133 | - dest = self.silo_state.dest |
134 | - ppa = self.silo_state.ppa |
135 | - for Build, source_names in self.types.items(): |
136 | - for name in source_names: |
137 | - self.builds[name] = Build(name, series, dest, ppa) |
138 | - if self.silo_state.dual: |
139 | - second = Secondary(name, series, dest, ppa) |
140 | - self.builds['zzz_' + name] = second |
141 | - |
142 | - def execute_phase(self, phase): |
143 | - """Execute a single phase for each available build. |
144 | - |
145 | - :param phase: The name of the phase to execute. |
146 | - :raises: A CITrainError in case anything goes wrong. |
147 | - """ |
148 | - log_value_of.phase('Beginning') |
149 | - nop = lambda *ignore: None |
150 | - getattr(BuildBase, 'pre_{}_phase'.format(phase), nop)(self.silo_state) |
151 | - for build in sorted(self.builds): |
152 | - getattr(self.builds[build], '{}_phase'.format(phase), nop)() |
153 | - if BuildBase.failures: |
154 | - raise BuildError('. '.join( |
155 | - fail.strip('. ') for fail in sorted(BuildBase.failures))) |
156 | - getattr(BuildBase, 'post_{}_phase'.format(phase), nop)(self.silo_state) |
157 | - |
158 | - |
159 | -def main(manager=BuildManager): |
160 | + |
161 | +def main(buildmanager=BuildManager): |
162 | """Execute the build, logging & saving any errors. |
163 | |
164 | :returns: 0 on success, 1 on any failure. |
165 | """ |
166 | - silo_state = SiloState(env.SILONAME, primary=True) |
167 | - buildmanager = manager(silo_state) |
168 | - phases = ['validate'] |
169 | - if env.WATCH_ONLY != 'true': |
170 | - phases += ['clean', 'collect', 'build', 'upload'] |
171 | - phases += ['watch', 'diff'] |
172 | try: |
173 | - buildmanager.do(*phases) |
174 | + silo_state = SiloState(env.SILONAME, primary=True) |
175 | + manager = buildmanager(silo_state) |
176 | + manager.do('validate') |
177 | + if env.WATCH_ONLY != 'true': |
178 | + manager.do('clean', 'collect', 'build', 'upload') |
179 | + manager.include_all() |
180 | + manager.do('watch', 'diff') |
181 | silo_state.status = 'Packages built.' |
182 | except CITrainError as err: |
183 | logging.error(str(err)) |
184 | |
185 | === modified file 'citrain/merge_clean.py' |
186 | --- citrain/merge_clean.py 2015-09-21 22:21:12 +0000 |
187 | +++ citrain/merge_clean.py 2015-09-24 07:13:28 +0000 |
188 | @@ -37,19 +37,10 @@ |
189 | |
190 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) |
191 | |
192 | +from citrain.recipes.manager import Manager |
193 | from cupstream2distro.errors import CITrainError |
194 | from cupstream2distro.utils import env, run_script |
195 | from cupstream2distro.silomanager import SiloState |
196 | -from citrain.build import BuildManager |
197 | - |
198 | - |
199 | -class MergeManager(BuildManager): |
200 | - """Instantiate Build objects necessary for merging.""" |
201 | - |
202 | - def choose_packages(self): |
203 | - """Act on all silo packages.""" |
204 | - self.names = set(self.silo_state.all_projects) |
205 | - logging.info('Including {}.'.format(', '.join(self.names))) |
206 | |
207 | |
208 | def main(): |
209 | @@ -59,7 +50,7 @@ |
210 | """ |
211 | try: |
212 | silo_state = SiloState(env.SILONAME, primary=True) |
213 | - MergeManager(silo_state).do( |
214 | + Manager(silo_state).do( |
215 | 'validate', 'enumeration', 'merge', 'push', 'nuke') |
216 | silo_state.status = 'Landed' |
217 | except CITrainError as err: |
218 | |
219 | === modified file 'citrain/migration.py' |
220 | --- citrain/migration.py 2015-09-11 00:25:12 +0000 |
221 | +++ citrain/migration.py 2015-09-24 07:13:28 +0000 |
222 | @@ -31,10 +31,11 @@ |
223 | |
224 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) |
225 | |
226 | +from citrain.recipes.manager import Manager |
227 | from cupstream2distro.errors import CITrainError |
228 | from cupstream2distro.utils import env, run_script |
229 | from cupstream2distro.silomanager import SiloState |
230 | -from citrain.merge_clean import MergeManager, main as merge_main |
231 | +from citrain.merge_clean import main as merge_main |
232 | |
233 | |
234 | def main(): |
235 | @@ -46,9 +47,8 @@ |
236 | env.SILONAME = silo_state |
237 | if silo_state.is_published: |
238 | logging.info('Inspecting silo {}:'.format(silo_state.ppa.web_link)) |
239 | - mergemanager = MergeManager(silo_state) |
240 | try: |
241 | - mergemanager.do('migration') |
242 | + Manager(silo_state).do('migration') |
243 | merge_main() |
244 | except CITrainError as err: |
245 | logging.info(str(err) + '\n') |
246 | |
247 | === modified file 'citrain/publisher.py' |
248 | --- citrain/publisher.py 2015-09-22 18:51:46 +0000 |
249 | +++ citrain/publisher.py 2015-09-24 07:13:28 +0000 |
250 | @@ -43,7 +43,7 @@ |
251 | |
252 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) |
253 | |
254 | -from citrain.merge_clean import MergeManager |
255 | +from citrain.recipes.manager import Manager |
256 | from cupstream2distro.version import V |
257 | from cupstream2distro.archive import Archive |
258 | from cupstream2distro.branchhandling import Branch |
259 | @@ -210,7 +210,7 @@ |
260 | silo_state = SiloState(env.SILONAME, primary=True) |
261 | dest = silo_state.dest |
262 | ppa = silo_state.ppa |
263 | - MergeManager(silo_state).do( |
264 | + Manager(silo_state).do( |
265 | 'checkstatus', 'validate', 'diff', 'checkupload', 'ackaging') |
266 | get_distro_and_series(silo_state.series) |
267 | silo_state.status = 'Publishing.' |
268 | |
269 | === added file 'citrain/recipes/manager.py' |
270 | --- citrain/recipes/manager.py 1970-01-01 00:00:00 +0000 |
271 | +++ citrain/recipes/manager.py 2015-09-24 07:13:28 +0000 |
272 | @@ -0,0 +1,109 @@ |
273 | +# Copyright (C) 2015 Canonical |
274 | +# |
275 | +# This program is free software; you can redistribute it and/or modify it under |
276 | +# the terms of the GNU General Public License as published by the Free Software |
277 | +# Foundation; version 3. |
278 | +# |
279 | +# This program is distributed in the hope that it will be useful, but WITHOUT |
280 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
281 | +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
282 | +# details. |
283 | +# |
284 | +# You should have received a copy of the GNU General Public License along with |
285 | +# this program; if not, write to the Free Software Foundation, Inc., |
286 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
287 | + |
288 | +"""CI Train Manager Classes |
289 | + |
290 | +These classes manage the instantiation of recipes and execution of phases. |
291 | +""" |
292 | + |
293 | +import logging |
294 | +import sys |
295 | +import os |
296 | + |
297 | +sys.path.append(os.path.dirname(os.path.dirname(__file__))) |
298 | + |
299 | +from citrain.recipes.base import BuildBase |
300 | +from citrain.recipes.merge import Merge |
301 | +from citrain.recipes.manual import Manual |
302 | +from citrain.recipes.secondary import Secondary |
303 | +from citrain.recipes.sourcesync import SourceSync |
304 | +from citrain.recipes.binarysync import BinarySync |
305 | +from cupstream2distro.errors import CITrainError |
306 | +from cupstream2distro.utils import env, log_value_of |
307 | + |
308 | + |
309 | +class Manager: |
310 | + """Coordinate instantiation & execution of build recipes.""" |
311 | + |
312 | + def __init__(self, silo_state): |
313 | + self.silo_state = silo_state |
314 | + self.names = set() |
315 | + self.phases = [] |
316 | + self.builds = {} |
317 | + self.types = {} |
318 | + |
319 | + def do(self, *phases): |
320 | + """Perform all specified phases. |
321 | + |
322 | + :param phases: A list of phase name strings. |
323 | + :raises: CITrainError in case anything goes wrong. |
324 | + """ |
325 | + if not self.types: |
326 | + self.choose_packages() |
327 | + self.choose_classes() |
328 | + self.instantiate_build_objects() |
329 | + for phase in phases: |
330 | + self.execute_phase(phase) |
331 | + |
332 | + def include_all(self): |
333 | + """Nop, implemented by subclass.""" |
334 | + pass |
335 | + |
336 | + def choose_packages(self): |
337 | + """Act on all silo packages.""" |
338 | + self.names = set(self.silo_state.all_projects) |
339 | + logging.info('Including {}.'.format(', '.join(self.names))) |
340 | + |
341 | + def choose_classes(self): |
342 | + """Decide which class to use for each individual package build.""" |
343 | + include_binaries = env.INCLUDE_BINARIES_IN_SYNC == 'true' |
344 | + Sync = BinarySync if include_binaries else SourceSync |
345 | + Source = Sync if self.silo_state.source_archive else Manual |
346 | + self.types = { |
347 | + Merge: self.names & set(self.silo_state.mps), |
348 | + Source: self.names & set(self.silo_state.sources), |
349 | + } |
350 | + if self.silo_state.source_archive: |
351 | + Sync.from_archive = self.silo_state.source_archive |
352 | + Sync.from_series = self.silo_state.source_series |
353 | + Merge.all_mps = self.silo_state.mps |
354 | + |
355 | + def instantiate_build_objects(self): |
356 | + """Instantiate the chosen classes for each chosen package.""" |
357 | + series = self.silo_state.series |
358 | + dest = self.silo_state.dest |
359 | + ppa = self.silo_state.ppa |
360 | + for Build, source_names in self.types.items(): |
361 | + for name in source_names: |
362 | + self.builds[name] = Build(name, series, dest, ppa) |
363 | + if self.silo_state.dual: |
364 | + second = Secondary(name, series, dest, ppa) |
365 | + self.builds['zzz_' + name] = second |
366 | + |
367 | + def execute_phase(self, phase): |
368 | + """Execute a single phase for each available build. |
369 | + |
370 | + :param phase: The name of the phase to execute. |
371 | + :raises: A CITrainError in case anything goes wrong. |
372 | + """ |
373 | + log_value_of.phase('Beginning') |
374 | + nop = lambda *ignore: None |
375 | + getattr(BuildBase, 'pre_{}_phase'.format(phase), nop)(self.silo_state) |
376 | + for build in sorted(self.builds): |
377 | + getattr(self.builds[build], '{}_phase'.format(phase), nop)() |
378 | + if BuildBase.failures: |
379 | + raise CITrainError('. '.join( |
380 | + fail.strip('. ') for fail in sorted(BuildBase.failures))) |
381 | + getattr(BuildBase, 'post_{}_phase'.format(phase), nop)(self.silo_state) |
382 | |
383 | === modified file 'citrain/recipes/merge.py' |
384 | --- citrain/recipes/merge.py 2015-09-09 00:14:07 +0000 |
385 | +++ citrain/recipes/merge.py 2015-09-24 07:13:28 +0000 |
386 | @@ -221,6 +221,7 @@ |
387 | |
388 | def merge_phase(self): |
389 | """Merge destination trunk back into local branch, if necessary.""" |
390 | + self.revert_branch() |
391 | target = self.target = Merge.all_mps[self.name][0].target_branch |
392 | logging.info('Merging {} to {}.'.format(target.web_link, self.path)) |
393 | self.merge_branch(target.web_link, 'Resync trunk.', unchanged=False) |
394 | |
395 | === modified file 'citrain/revert.py' |
396 | --- citrain/revert.py 2015-06-23 20:07:17 +0000 |
397 | +++ citrain/revert.py 2015-09-24 07:13:28 +0000 |
398 | @@ -45,11 +45,12 @@ |
399 | |
400 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) |
401 | |
402 | +from citrain.recipes.manager import Manager |
403 | +from citrain.recipes.sourcesync import SourceSync |
404 | from cupstream2distro.version import V |
405 | -from citrain.merge_clean import MergeManager |
406 | from cupstream2distro.project import DotProject |
407 | from cupstream2distro.archive import sort_by_date |
408 | -from citrain.build import SourceSync, main as build_main |
409 | +from citrain.build import main as build_main |
410 | from cupstream2distro.errors import RevertError |
411 | from cupstream2distro.utils import ( |
412 | SILO_DIR, |
413 | @@ -101,7 +102,7 @@ |
414 | DotProject.soft_save(self.name, dest=current, ours=new_version) |
415 | |
416 | |
417 | -class RevertManager(MergeManager): |
418 | +class RevertManager(Manager): |
419 | """Orchestrate the reverting of packages.""" |
420 | |
421 | def choose_classes(self): |
422 | |
423 | === modified file 'cupstream2distro/branchhandling.py' |
424 | --- cupstream2distro/branchhandling.py 2015-09-11 19:50:59 +0000 |
425 | +++ cupstream2distro/branchhandling.py 2015-09-24 07:13:28 +0000 |
426 | @@ -129,6 +129,10 @@ |
427 | log_call('bzr init .', cwd=self.path) |
428 | log_call('bzr add .', cwd=self.path) |
429 | |
430 | + def revert_branch(self): |
431 | + """Revert any changes in the branch.""" |
432 | + log_call('bzr revert', cwd=self.path) |
433 | + |
434 | def get_branch(self, url): |
435 | """Branch url to self.path. |
436 | |
437 | |
438 | === modified file 'cupstream2distro/packagelist.py' (properties changed: +x to -x) |
439 | === modified file 'cupstream2distro/packagemanager.py' |
440 | --- cupstream2distro/packagemanager.py 2015-09-14 06:12:33 +0000 |
441 | +++ cupstream2distro/packagemanager.py 2015-09-24 07:13:28 +0000 |
442 | @@ -160,8 +160,11 @@ |
443 | def get_package_version(self): |
444 | """Get newest version from debian changelog.""" |
445 | key = 'Version: ' |
446 | - instance, stdout, stderr = call(['dpkg-parsechangelog'], cwd=self.path) |
447 | - if instance.returncode != 0: |
448 | + try: |
449 | + inst, stdout, stderr = call(['dpkg-parsechangelog'], cwd=self.path) |
450 | + except FileNotFoundError: |
451 | + return None |
452 | + if inst.returncode != 0: |
453 | raise PackageError(stderr) |
454 | for line in stdout.splitlines(): |
455 | if line.startswith(key): |
456 | |
457 | === modified file 'cupstream2distro/utils.py' |
458 | --- cupstream2distro/utils.py 2015-09-22 06:53:49 +0000 |
459 | +++ cupstream2distro/utils.py 2015-09-24 07:13:28 +0000 |
460 | @@ -21,15 +21,14 @@ |
461 | import logging |
462 | import subprocess |
463 | |
464 | -from glob import glob |
465 | from six import text_type |
466 | from functools import wraps |
467 | from base64 import b64encode |
468 | from pickle import dumps, loads |
469 | from inspect import currentframe |
470 | from contextlib import contextmanager |
471 | +from os.path import exists, isfile, join |
472 | from six.moves.urllib.parse import unquote |
473 | -from os.path import basename, exists, isfile, join |
474 | |
475 | from cupstream2distro.settings import SILOS_DIR |
476 | |
477 | @@ -43,15 +42,6 @@ |
478 | return '/'.join([ppa.owner.name, ppa.distribution.name, ppa.name]) |
479 | |
480 | |
481 | -def find_all_uploaded(): |
482 | - """Return all source package names and versions uploaded to the ppa. |
483 | - |
484 | - :yields: Source package names that have been uploaded. |
485 | - """ |
486 | - for uploaded in glob(SILO_DIR('*_source.ppa.upload')): |
487 | - yield basename(uploaded).split('_')[0] |
488 | - |
489 | - |
490 | @contextmanager |
491 | def suppress(*exceptions): |
492 | """Silence the given exceptions.""" |
493 | |
494 | === modified file 'tests/unit/test_branchhandling.py' |
495 | --- tests/unit/test_branchhandling.py 2015-09-11 20:00:49 +0000 |
496 | +++ tests/unit/test_branchhandling.py 2015-09-24 07:13:28 +0000 |
497 | @@ -77,6 +77,12 @@ |
498 | ]) |
499 | |
500 | @patch('cupstream2distro.branchhandling.log_call') |
501 | + def test_revert_branch(self, call_mock): |
502 | + """Correctly revert branches.""" |
503 | + self.branch.revert_branch() |
504 | + call_mock.assert_called_once_with('bzr revert', cwd=self.branch.path) |
505 | + |
506 | + @patch('cupstream2distro.branchhandling.log_call') |
507 | def test_branching(self, call_mock): |
508 | """We correcly branch a branch.""" |
509 | path = self.branch.path = join(self.tempdir, 'foo') |
510 | |
511 | === modified file 'tests/unit/test_packagemanager.py' |
512 | --- tests/unit/test_packagemanager.py 2015-09-14 06:52:53 +0000 |
513 | +++ tests/unit/test_packagemanager.py 2015-09-24 07:13:28 +0000 |
514 | @@ -123,6 +123,11 @@ |
515 | with utf8_open(self.package.debian_changelog) as data: |
516 | self.assertEqual(data.read(), expected) |
517 | |
518 | + def test_get_package_version_nonexistant_dir(self): |
519 | + """Get latest packaging version.""" |
520 | + self.package.path = '/totally/nonexistant' |
521 | + self.assertIsNone(self.package.get_package_version()) |
522 | + |
523 | def test_get_package_version(self): |
524 | """Get latest packaging version.""" |
525 | self.prep_debian_file('changelog', s.NESTED_CHANGELOG) |
526 | |
527 | === modified file 'tests/unit/test_recipe_binarysync.py' |
528 | --- tests/unit/test_recipe_binarysync.py 2015-08-21 05:56:14 +0000 |
529 | +++ tests/unit/test_recipe_binarysync.py 2015-09-24 07:13:28 +0000 |
530 | @@ -16,7 +16,7 @@ |
531 | |
532 | """Tests for CI Train Binary Sync Recipe.""" |
533 | |
534 | -from mock import Mock |
535 | +from mock import Mock, patch |
536 | |
537 | from tests.unit import DirectoryAwareTestCase |
538 | |
539 | @@ -33,6 +33,7 @@ |
540 | self.series = Mock() |
541 | self.ppa = Mock() |
542 | |
543 | + @patch('citrain.recipes.binarysync.BinarySync.get_archive_version', Mock()) |
544 | def test_binarysync_upload_phase(self): |
545 | """Copy package binaries from one archive to another.""" |
546 | from_archive = BinarySync.from_archive = Mock() |
547 | |
548 | === added file 'tests/unit/test_recipe_manager.py' |
549 | --- tests/unit/test_recipe_manager.py 1970-01-01 00:00:00 +0000 |
550 | +++ tests/unit/test_recipe_manager.py 2015-09-24 07:13:28 +0000 |
551 | @@ -0,0 +1,154 @@ |
552 | +# Copyright: (C) 2015 Canonical |
553 | +# |
554 | +# This program is free software; you can redistribute it and/or modify it under |
555 | +# the terms of the GNU General Public License as published by the Free Software |
556 | +# Foundation; version 3. |
557 | +# |
558 | +# This program is distributed in the hope that it will be useful, but WITHOUT |
559 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
560 | +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
561 | +# details. |
562 | +# |
563 | +# You should have received a copy of the GNU General Public License along with |
564 | +# this program; if not, write to the Free Software Foundation, Inc., |
565 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
566 | + |
567 | +"""Tests for CI Train Recipe Manager.""" |
568 | + |
569 | +from mock import Mock, call, patch |
570 | + |
571 | +from tests.unit import DirectoryAwareTestCase |
572 | + |
573 | +from citrain.recipes.manager import Manager |
574 | +from cupstream2distro.errors import CITrainError |
575 | +from cupstream2distro.utils import env |
576 | + |
577 | +# Unused import necessary for code coverage reporting |
578 | +from citrain import build as build_module |
579 | +COVERAGE = [build_module] |
580 | + |
581 | + |
582 | +class BuildTestCase(DirectoryAwareTestCase): |
583 | + """Test CI Train Recipe Manager.""" |
584 | + |
585 | + def test_manager_do(self): |
586 | + """Run the specified phases.""" |
587 | + silo_state = Mock() |
588 | + bman = Manager(silo_state) |
589 | + bman.choose_packages = Mock() |
590 | + bman.choose_classes = Mock() |
591 | + bman.instantiate_build_objects = Mock() |
592 | + bman.execute_phase = Mock() |
593 | + bman.do('solid', 'liquid', 'gas') |
594 | + bman.choose_packages.assert_called_once_with() |
595 | + bman.choose_classes.assert_called_once_with() |
596 | + bman.instantiate_build_objects.assert_called_once_with() |
597 | + self.assertEqual( |
598 | + bman.execute_phase.mock_calls, [ |
599 | + call('solid'), call('liquid'), call('gas') |
600 | + ]) |
601 | + |
602 | + def test_manager_include_all(self): |
603 | + """Do nothing.""" |
604 | + Manager(Mock()).include_all() |
605 | + |
606 | + def test_manager_choose_packages(self): |
607 | + """Manager should choose all packages.""" |
608 | + silo_state = Mock(all_projects=list('foobar')) |
609 | + manager = Manager(silo_state) |
610 | + manager.choose_packages() |
611 | + self.assertEqual(manager.names, set(['f', 'o', 'b', 'a', 'r'])) |
612 | + |
613 | + @patch('citrain.recipes.manager.Merge') |
614 | + @patch('citrain.recipes.manager.SourceSync') |
615 | + def test_manager_choose_classes(self, source, merge): |
616 | + """Determine what classes to build with.""" |
617 | + silo_state = Mock( |
618 | + all_projects=['a', 'b', 'c'], mps=['a'], sources=['b', 'c']) |
619 | + env.INCLUDE_BINARIES_IN_SYNC = 'false' |
620 | + bman = Manager(silo_state) |
621 | + bman.names = set(['a', 'b']) |
622 | + bman.choose_classes() |
623 | + self.assertEqual( |
624 | + bman.types, { |
625 | + merge: set(['a']), |
626 | + source: set(['b']), |
627 | + }) |
628 | + self.assertEqual(merge.all_mps, silo_state.mps) |
629 | + self.assertEqual(source.from_series, silo_state.source_series) |
630 | + |
631 | + def test_manager_instantiate_build_objects(self): |
632 | + """Create all build objects.""" |
633 | + silo_state = Mock( |
634 | + all_projects=['a', 'b', 'c'], mps=['a'], sources=['b', 'c'], |
635 | + dual=None) |
636 | + merge = Mock() |
637 | + source = Mock() |
638 | + bman = Manager(silo_state) |
639 | + bman.types = { |
640 | + merge: set('a'), |
641 | + source: set('b'), |
642 | + } |
643 | + bman.instantiate_build_objects() |
644 | + self.assertEqual( |
645 | + bman.builds, { |
646 | + 'a': merge.return_value, |
647 | + 'b': source.return_value, |
648 | + }) |
649 | + merge.assert_called_once_with( |
650 | + 'a', silo_state.series, silo_state.dest, silo_state.ppa) |
651 | + source.assert_called_once_with( |
652 | + 'b', silo_state.series, silo_state.dest, silo_state.ppa) |
653 | + |
654 | + @patch('citrain.recipes.manager.Secondary') |
655 | + def test_manager_instantiate_build_objs_scndry(self, second): |
656 | + """Create Secondary build objects.""" |
657 | + silo_state = Mock( |
658 | + all_projects=['a', 'b', 'c'], mps=['a'], sources=['b', 'c'], |
659 | + dual='vivid') |
660 | + merge = Mock() |
661 | + source = Mock() |
662 | + bman = Manager(silo_state) |
663 | + bman.types = { |
664 | + merge: set('a'), |
665 | + source: set('b'), |
666 | + } |
667 | + bman.instantiate_build_objects() |
668 | + self.assertEqual( |
669 | + bman.builds, { |
670 | + 'a': merge.return_value, |
671 | + 'b': source.return_value, |
672 | + 'zzz_a': second.return_value, |
673 | + 'zzz_b': second.return_value, |
674 | + }) |
675 | + |
676 | + @patch('citrain.recipes.manager.BuildBase') |
677 | + def test_manager_execute_phase(self, bbase): |
678 | + """Execute one phase for all builds.""" |
679 | + silo_state = Mock() |
680 | + bbase.failures = set() |
681 | + bman = Manager(silo_state) |
682 | + merge = Mock() |
683 | + sync = Mock() |
684 | + bman.builds = {'a': merge, 'b': sync} |
685 | + bman.execute_phase('liquid') |
686 | + bbase.pre_liquid_phase.assert_called_once_with(silo_state) |
687 | + merge.liquid_phase.assert_called_once_with() |
688 | + sync.liquid_phase.assert_called_once_with() |
689 | + bbase.post_liquid_phase.assert_called_once_with(silo_state) |
690 | + |
691 | + @patch('citrain.recipes.manager.BuildBase') |
692 | + def test_manager_execute_phase_failures(self, bbase): |
693 | + """Raise error when phase sets a failure.""" |
694 | + silo_state = Mock() |
695 | + bbase.failures = {'something broke', 'foo'} |
696 | + bman = Manager(silo_state) |
697 | + merge = Mock() |
698 | + sync = Mock() |
699 | + bman.builds = {'a': merge, 'b': sync} |
700 | + with self.assertRaisesRegexp(CITrainError, 'foo. something broke'): |
701 | + bman.execute_phase('liquid') |
702 | + bbase.pre_liquid_phase.assert_called_once_with(silo_state) |
703 | + merge.liquid_phase.assert_called_once_with() |
704 | + sync.liquid_phase.assert_called_once_with() |
705 | + self.assertEqual(bbase.post_liquid_phase.mock_calls, []) |
706 | |
707 | === modified file 'tests/unit/test_recipe_merge.py' |
708 | --- tests/unit/test_recipe_merge.py 2015-09-23 03:36:24 +0000 |
709 | +++ tests/unit/test_recipe_merge.py 2015-09-24 07:13:28 +0000 |
710 | @@ -370,12 +370,14 @@ |
711 | |
712 | @patch('citrain.recipes.merge.lp') |
713 | @patch('citrain.recipes.merge.Merge.merge_branch', Mock()) |
714 | + @patch('citrain.recipes.merge.Merge.revert_branch', Mock()) |
715 | def test_merge_merge_phase(self, lp_mock): |
716 | """Merge target back to branch before pushing.""" |
717 | merge1, merge2 = [Mock(target_branch=Mock(web_link='example.biz'))] * 2 |
718 | Merge.all_mps = {'foo-pack': [merge1, merge2]} |
719 | merge = Merge('foo-pack', self.series, self.dest, self.ppa) |
720 | merge.merge_phase() |
721 | + merge.revert_branch.assert_called_once_with() |
722 | merge.merge_branch.assert_called_once_with( |
723 | 'example.biz', 'Resync trunk.', unchanged=False) |
724 | |
725 | |
726 | === modified file 'tests/unit/test_recipe_secondary.py' |
727 | --- tests/unit/test_recipe_secondary.py 2015-09-22 06:53:49 +0000 |
728 | +++ tests/unit/test_recipe_secondary.py 2015-09-24 07:13:28 +0000 |
729 | @@ -66,6 +66,7 @@ |
730 | @patch(MOD + 'lp') |
731 | @patch(MOD + 'os') |
732 | @patch(MOD + 'shutil') |
733 | + @patch(MOD + 'Secondary.get_package_version', Mock()) |
734 | @patch(MOD + 'Secondary.correct_package_changelog', Mock()) |
735 | def test_secondary_collect_phase(self, sh_mock, os_mock, lp_mock): |
736 | """Ensure secondary collection works.""" |
737 | @@ -86,6 +87,7 @@ |
738 | @patch(MOD + 'lp') |
739 | @patch(MOD + 'os') |
740 | @patch(MOD + 'shutil') |
741 | + @patch(MOD + 'Secondary.get_package_version', Mock()) |
742 | @patch(MOD + 'Secondary.correct_package_changelog', Mock()) |
743 | def test_secondary_collect_phase_skip(self, sh_mock, os_mock, lp_mock): |
744 | """Secondary collection should ignore manual sources, binary syncs.""" |
745 | |
746 | === modified file 'tests/unit/test_script_abandon.py' |
747 | --- tests/unit/test_script_abandon.py 2015-09-21 23:16:33 +0000 |
748 | +++ tests/unit/test_script_abandon.py 2015-09-24 07:13:28 +0000 |
749 | @@ -36,15 +36,15 @@ |
750 | silo_state._siloname = 'ubuntu/landing-xyz' |
751 | self.script.SiloState.requestid.fget.cache = {} |
752 | self.script.env.REQUEST_ID = '500' |
753 | - self.script.MergeManager = Mock() |
754 | - mergemanager = self.script.MergeManager.return_value |
755 | + self.script.Manager = Mock() |
756 | + mergemanager = self.script.Manager.return_value |
757 | self.assertEqual(self.script.main(), 0) |
758 | self.assertEqual(self.script.SiloState.requestid.fget.cache, { |
759 | (silo_state,): '500' |
760 | }) |
761 | self.script.SiloState.assert_called_once_with( |
762 | siloname=None, primary=False) |
763 | - self.script.MergeManager.assert_called_once_with(silo_state) |
764 | + self.script.Manager.assert_called_once_with(silo_state) |
765 | self.assertEqual(silo_state.status, 'Abandoned') |
766 | mergemanager.do.assert_called_once_with('nuke') |
767 | silo_state.save_config.assert_called_once_with() |
768 | @@ -55,11 +55,11 @@ |
769 | silo_state._siloname = None |
770 | self.script.SiloState.requestid.fget.cache = {} |
771 | self.script.env.REQUEST_ID = '500' |
772 | - self.script.MergeManager = Mock() |
773 | + self.script.Manager = Mock() |
774 | self.assertEqual(self.script.main(), 0) |
775 | self.script.SiloState.assert_called_once_with( |
776 | siloname=None, primary=False) |
777 | - self.assertEqual(self.script.MergeManager.mock_calls, []) |
778 | + self.assertEqual(self.script.Manager.mock_calls, []) |
779 | self.assertEqual(silo_state.status, 'Abandoned') |
780 | silo_state.save_config.assert_called_once_with() |
781 | |
782 | @@ -69,8 +69,8 @@ |
783 | silo_state._siloname = 'ubuntu/landing-xyz' |
784 | self.script.SiloState.requestid.fget.cache = {} |
785 | self.script.env.REQUEST_ID = '500' |
786 | - self.script.MergeManager = Mock() |
787 | - mergemanager = self.script.MergeManager.return_value |
788 | + self.script.Manager = Mock() |
789 | + mergemanager = self.script.Manager.return_value |
790 | mergemanager.do.side_effect = CITrainError('failboat.') |
791 | self.assertEqual(self.script.main(), 0) |
792 | self.assertEqual(self.script.SiloState.requestid.fget.cache, { |
793 | @@ -78,7 +78,7 @@ |
794 | }) |
795 | self.script.SiloState.assert_called_once_with( |
796 | siloname=None, primary=False) |
797 | - self.script.MergeManager.assert_called_once_with(silo_state) |
798 | + self.script.Manager.assert_called_once_with(silo_state) |
799 | self.assertEqual(silo_state.status, 'Abandoned') |
800 | mergemanager.do.assert_called_once_with('nuke') |
801 | silo_state.save_config.assert_called_once_with() |
802 | |
803 | === modified file 'tests/unit/test_script_build.py' |
804 | --- tests/unit/test_script_build.py 2015-09-14 17:52:10 +0000 |
805 | +++ tests/unit/test_script_build.py 2015-09-24 07:13:28 +0000 |
806 | @@ -50,29 +50,47 @@ |
807 | |
808 | def setUp(self): |
809 | super().setUp() |
810 | - self.script.BuildBase.__bases__ = (fake_factory(),) |
811 | self.script.glob = Mock() |
812 | self.source = Mock() |
813 | self.dest = Mock() |
814 | self.series = Mock() |
815 | self.ppa = Mock() |
816 | |
817 | - def test_buildmanager_do(self): |
818 | - """Run the specified phases.""" |
819 | - silo_state = Mock() |
820 | - bman = self.script.BuildManager(silo_state) |
821 | - bman.choose_packages = Mock() |
822 | - bman.choose_classes = Mock() |
823 | - bman.instantiate_build_objects = Mock() |
824 | - bman.execute_phase = Mock() |
825 | - bman.do('solid', 'liquid', 'gas') |
826 | - bman.choose_packages.assert_called_once_with() |
827 | - bman.choose_classes.assert_called_once_with() |
828 | - bman.instantiate_build_objects.assert_called_once_with() |
829 | - self.assertEqual( |
830 | - bman.execute_phase.mock_calls, [ |
831 | - call('solid'), call('liquid'), call('gas') |
832 | - ]) |
833 | + def test_find_all_uploaded(self): |
834 | + """Find everything that has been uploaded from this silo.""" |
835 | + self.script.glob.return_value = [ |
836 | + '/path/to/foo_0.1_source.ppa.upload', |
837 | + '/path/to/bar_0.2_source.ppa.upload', |
838 | + ] |
839 | + self.assertEqual( |
840 | + sorted(self.script.find_all_uploaded()), ['bar', 'foo']) |
841 | + |
842 | + def test_find_all_uploaded_multiple_series(self): |
843 | + """We can handle uploading multiple series from a single silo.""" |
844 | + self.script.glob.return_value = [ |
845 | + '/path/to/foo_0.1_source.ppa.upload', |
846 | + '/path/to/foo_0.1~utopic_source.ppa.upload', |
847 | + '/path/to/bar_0.2_source.ppa.upload', |
848 | + '/path/to/bar_0.2~utopic_source.ppa.upload', |
849 | + ] |
850 | + self.assertEqual( |
851 | + sorted(self.script.find_all_uploaded()), |
852 | + ['bar', 'bar', 'foo', 'foo']) |
853 | + self.assertEqual( |
854 | + set(self.script.find_all_uploaded()), set(['foo', 'bar'])) |
855 | + |
856 | + def test_buildmanager_include_all(self): |
857 | + """Correctly switch to watching all packages.""" |
858 | + bman = self.script.BuildManager(Mock()) |
859 | + bman.types['foo'] = 'bar' |
860 | + self.assertEqual( |
861 | + bman.choose_packages.__doc__, |
862 | + 'Decide which packages need to be built.') |
863 | + bman.include_all() |
864 | + self.assertEqual( |
865 | + bman.choose_packages.__doc__, |
866 | + 'Act on all silo packages.') |
867 | + self.assertFalse(bman.types) |
868 | |
869 | def test_buildmanager_choose_packages(self): |
870 | """Determine what packages to act upon.""" |
871 | @@ -96,107 +114,6 @@ |
872 | with self.assertRaisesRegexp(BuildError, 'No packages are being'): |
873 | bman.choose_packages() |
874 | self.assertEqual(bman.names, set()) |
875 | - self.assertIsNone(bman.do('ignored')) |
876 | - |
877 | - def test_buildmanager_choose_classes(self): |
878 | - """Determine what classes to build with.""" |
879 | - silo_state = Mock( |
880 | - all_projects=['a', 'b', 'c'], mps=['a'], sources=['b', 'c']) |
881 | - self.script.env.INCLUDE_BINARIES_IN_SYNC = 'false' |
882 | - bman = self.script.BuildManager(silo_state) |
883 | - bman.names = set(['a', 'b']) |
884 | - bman.choose_classes() |
885 | - self.assertEqual( |
886 | - bman.types, { |
887 | - self.script.Merge: set(['a']), |
888 | - self.script.SourceSync: set(['b']), |
889 | - }) |
890 | - self.assertEqual(self.script.Merge.all_mps, silo_state.mps) |
891 | - self.assertEqual( |
892 | - self.script.SourceSync.from_series, |
893 | - silo_state.source_series) |
894 | - |
895 | - def test_buildmanager_instantiate_build_objects(self): |
896 | - """Create all build objects.""" |
897 | - silo_state = Mock( |
898 | - all_projects=['a', 'b', 'c'], mps=['a'], sources=['b', 'c'], |
899 | - dual=None) |
900 | - self.script.lp.load = lambda x: x |
901 | - merge = Mock() |
902 | - source = Mock() |
903 | - bman = self.script.BuildManager(silo_state) |
904 | - bman.types = { |
905 | - merge: set('a'), |
906 | - source: set('b'), |
907 | - } |
908 | - bman.instantiate_build_objects() |
909 | - self.assertEqual( |
910 | - bman.builds, { |
911 | - 'a': merge.return_value, |
912 | - 'b': source.return_value, |
913 | - }) |
914 | - merge.assert_called_once_with( |
915 | - 'a', silo_state.series, silo_state.dest, silo_state.ppa) |
916 | - source.assert_called_once_with( |
917 | - 'b', silo_state.series, silo_state.dest, silo_state.ppa) |
918 | - |
919 | - def test_buildmanager_instantiate_build_objects_secondary(self): |
920 | - """Create Secondary build objects.""" |
921 | - silo_state = Mock( |
922 | - all_projects=['a', 'b', 'c'], mps=['a'], sources=['b', 'c'], |
923 | - dual='vivid') |
924 | - self.script.lp.load = lambda x: x |
925 | - merge = Mock() |
926 | - source = Mock() |
927 | - bman = self.script.BuildManager(silo_state) |
928 | - bman.types = { |
929 | - merge: set('a'), |
930 | - source: set('b'), |
931 | - } |
932 | - self.script.Secondary = Mock() |
933 | - bman.instantiate_build_objects() |
934 | - self.assertEqual( |
935 | - bman.builds, { |
936 | - 'a': merge.return_value, |
937 | - 'b': source.return_value, |
938 | - 'zzz_a': self.script.Secondary.return_value, |
939 | - 'zzz_b': self.script.Secondary.return_value, |
940 | - }) |
941 | - |
942 | - def test_buildmanager_execute_phase(self): |
943 | - """Execute one phase for all builds.""" |
944 | - silo_state = Mock() |
945 | - self.script.BuildBase = Mock() |
946 | - self.script.BuildBase.failures = set() |
947 | - bman = self.script.BuildManager(silo_state) |
948 | - merge = Mock() |
949 | - sync = Mock() |
950 | - bman.builds = {'a': merge, 'b': sync} |
951 | - bman.execute_phase('liquid') |
952 | - self.script.BuildBase.pre_liquid_phase.assert_called_once_with( |
953 | - silo_state) |
954 | - merge.liquid_phase.assert_called_once_with() |
955 | - sync.liquid_phase.assert_called_once_with() |
956 | - self.script.BuildBase.post_liquid_phase.assert_called_once_with( |
957 | - silo_state) |
958 | - |
959 | - def test_buildmanager_execute_phase_failures(self): |
960 | - """Raise error when phase sets a failure.""" |
961 | - silo_state = Mock() |
962 | - self.script.BuildBase = Mock() |
963 | - self.script.BuildBase.failures = {'something broke', 'foo'} |
964 | - bman = self.script.BuildManager(silo_state) |
965 | - merge = Mock() |
966 | - sync = Mock() |
967 | - bman.builds = {'a': merge, 'b': sync} |
968 | - with self.assertRaisesRegexp(BuildError, 'foo. something broke'): |
969 | - bman.execute_phase('liquid') |
970 | - self.script.BuildBase.pre_liquid_phase.assert_called_once_with( |
971 | - silo_state) |
972 | - merge.liquid_phase.assert_called_once_with() |
973 | - sync.liquid_phase.assert_called_once_with() |
974 | - self.assertEqual( |
975 | - self.script.BuildBase.post_liquid_phase.mock_calls, []) |
976 | |
977 | def test_main(self): |
978 | """Run things without issue.""" |
979 | @@ -207,9 +124,12 @@ |
980 | bman.assert_called_once_with(silo_state) |
981 | self.assertEqual( |
982 | bman.return_value.mock_calls, [ |
983 | - call.do('validate', 'clean', 'collect', |
984 | - 'build', 'upload', 'watch', 'diff'), |
985 | + call.do('validate'), |
986 | + call.do('clean', 'collect', 'build', 'upload'), |
987 | + call.include_all(), |
988 | + call.do('watch', 'diff'), |
989 | ]) |
990 | + self.assertEqual(silo_state.status, 'Packages built.') |
991 | silo_state.save_config.assert_called_once_with() |
992 | |
993 | def test_main_watch_only(self): |
994 | @@ -221,7 +141,9 @@ |
995 | bman.assert_called_once_with(silo_state) |
996 | self.assertEqual( |
997 | bman.return_value.mock_calls, [ |
998 | - call.do('validate', 'watch', 'diff'), |
999 | + call.do('validate'), |
1000 | + call.include_all(), |
1001 | + call.do('watch', 'diff'), |
1002 | ]) |
1003 | silo_state.save_config.assert_called_once_with() |
1004 | |
1005 | @@ -239,8 +161,7 @@ |
1006 | bman.assert_called_once_with(silo_state) |
1007 | self.assertEqual( |
1008 | bman.return_value.mock_calls, [ |
1009 | - call.do('validate', 'clean', 'collect', |
1010 | - 'build', 'upload', 'watch', 'diff'), |
1011 | + call.do('validate'), |
1012 | ]) |
1013 | self.assertEqual(silo_state.status, 'Build failed: It asploded!') |
1014 | silo_state.save_config.assert_called_once_with() |
1015 | |
1016 | === modified file 'tests/unit/test_script_merge_clean.py' |
1017 | --- tests/unit/test_script_merge_clean.py 2015-09-22 07:27:29 +0000 |
1018 | +++ tests/unit/test_script_merge_clean.py 2015-09-24 07:13:28 +0000 |
1019 | @@ -31,21 +31,14 @@ |
1020 | """Test CI Train Merge & Clean script.""" |
1021 | scriptname = 'merge_clean.py' |
1022 | |
1023 | - def test_mergemanager_choose_packages(self): |
1024 | - """MergeManager should choose all packages.""" |
1025 | - silo_state = Mock(all_projects=list('foobar')) |
1026 | - mergemanager = self.script.MergeManager(silo_state) |
1027 | - mergemanager.choose_packages() |
1028 | - self.assertEqual(mergemanager.names, set(['f', 'o', 'b', 'a', 'r'])) |
1029 | - |
1030 | def test_main(self): |
1031 | """main() succeeds in the primary case.""" |
1032 | self.script.env.SILONAME = 'fred' |
1033 | - self.script.MergeManager = Mock() |
1034 | - mergemanager = self.script.MergeManager.return_value |
1035 | + self.script.Manager = Mock() |
1036 | + mergemanager = self.script.Manager.return_value |
1037 | self.assertEqual(self.script.main(), 0) |
1038 | self.script.SiloState.assert_called_once_with('fred', primary=True) |
1039 | - self.script.MergeManager.assert_called_once_with( |
1040 | + self.script.Manager.assert_called_once_with( |
1041 | self.script.SiloState.return_value) |
1042 | mergemanager.do.assert_called_once_with( |
1043 | 'validate', 'enumeration', 'merge', 'push', 'nuke') |
1044 | @@ -53,13 +46,13 @@ |
1045 | def test_main_failed(self): |
1046 | """main() returns 1 when a phase raises an exception.""" |
1047 | self.script.env.SILONAME = 'fred' |
1048 | - self.script.MergeManager = Mock() |
1049 | - mergemanager = self.script.MergeManager.return_value |
1050 | + self.script.Manager = Mock() |
1051 | + mergemanager = self.script.Manager.return_value |
1052 | mergemanager.do.side_effect = MergeError('whoa buddy!') |
1053 | silo_state = self.script.SiloState.return_value |
1054 | self.assertEqual(self.script.main(), 1) |
1055 | self.script.SiloState.assert_called_once_with('fred', primary=True) |
1056 | - self.script.MergeManager.assert_called_once_with( |
1057 | + self.script.Manager.assert_called_once_with( |
1058 | self.script.SiloState.return_value) |
1059 | mergemanager.do.assert_called_once_with( |
1060 | 'validate', 'enumeration', 'merge', 'push', 'nuke') |
1061 | |
1062 | === modified file 'tests/unit/test_script_migration.py' |
1063 | --- tests/unit/test_script_migration.py 2015-09-11 00:25:12 +0000 |
1064 | +++ tests/unit/test_script_migration.py 2015-09-24 07:13:28 +0000 |
1065 | @@ -35,7 +35,7 @@ |
1066 | |
1067 | def setUp(self): |
1068 | super().setUp() |
1069 | - self.script.MergeManager = Mock() |
1070 | + self.script.Manager = Mock() |
1071 | self.script.merge_main = Mock() |
1072 | self.script.glob.return_value = [ |
1073 | join(SILOS_DIR, 'ubuntu', 'landing-00{}'.format(x)) |
1074 | @@ -48,7 +48,7 @@ |
1075 | self.assertEqual(self.script.main(), 0) |
1076 | for state in states: |
1077 | self.assertEqual(state.mock_calls, []) |
1078 | - self.assertEqual(self.script.MergeManager.mock_calls, [ |
1079 | + self.assertEqual(self.script.Manager.mock_calls, [ |
1080 | call(states[0]), |
1081 | call().do('migration'), |
1082 | call(states[1]), |
1083 | @@ -62,7 +62,7 @@ |
1084 | """Don't check silos that are empty.""" |
1085 | self.script.SiloState.iterate.return_value = [] |
1086 | self.assertEqual(self.script.main(), 0) |
1087 | - self.assertEqual(self.script.MergeManager.mock_calls, []) |
1088 | + self.assertEqual(self.script.Manager.mock_calls, []) |
1089 | self.assertEqual(self.script.merge_main.mock_calls, []) |
1090 | |
1091 | def test_main_skip_unpublished_silos(self): |
1092 | @@ -70,7 +70,7 @@ |
1093 | states = self.script.SiloState.iterate.return_value = [ |
1094 | Mock(is_published=False) for rid in range(3)] |
1095 | self.assertEqual(self.script.main(), 0) |
1096 | - self.assertEqual(self.script.MergeManager.mock_calls, []) |
1097 | + self.assertEqual(self.script.Manager.mock_calls, []) |
1098 | self.assertEqual(self.script.merge_main.mock_calls, []) |
1099 | for state in states: |
1100 | self.assertEqual(state.set_migrating.mock_calls, []) |
1101 | @@ -80,7 +80,7 @@ |
1102 | """Don't merge silos that are still migrating.""" |
1103 | states = self.script.SiloState.iterate.return_value = [ |
1104 | Mock(requestid=str(rid)) for rid in range(3)] |
1105 | - self.script.MergeManager.return_value.do.side_effect = MigrationError( |
1106 | + self.script.Manager.return_value.do.side_effect = MigrationError( |
1107 | 'foo is in the Proposed pocket.') |
1108 | self.assertEqual(self.script.main(), 0) |
1109 | for state in states: |
1110 | @@ -89,7 +89,7 @@ |
1111 | self.assertEqual(state.mock_calls, [ |
1112 | call.save_config(), |
1113 | ]) |
1114 | - self.assertEqual(self.script.MergeManager.mock_calls, [ |
1115 | + self.assertEqual(self.script.Manager.mock_calls, [ |
1116 | call(states[0]), |
1117 | call().do('migration'), |
1118 | call(states[1]), |
1119 | |
1120 | === modified file 'tests/unit/test_script_publisher.py' |
1121 | --- tests/unit/test_script_publisher.py 2015-09-22 18:51:46 +0000 |
1122 | +++ tests/unit/test_script_publisher.py 2015-09-24 07:13:28 +0000 |
1123 | @@ -413,7 +413,7 @@ |
1124 | |
1125 | def mock_main(self): |
1126 | """Ensure enough of the publisher is mocked out for testing main().""" |
1127 | - self.script.MergeManager = Mock() |
1128 | + self.script.Manager = Mock() |
1129 | self.script.get_distro_and_series = Mock() |
1130 | self.script.check_versions_at_destination = Mock() |
1131 | self.script.check_for_unapproved = Mock() |
1132 | @@ -430,8 +430,8 @@ |
1133 | dest = state.dest |
1134 | ppa = state.ppa |
1135 | self.assertEqual(self.script.main(), 0) |
1136 | - self.script.MergeManager.assert_called_once_with(state) |
1137 | - self.script.MergeManager.return_value.do.assert_called_once_with( |
1138 | + self.script.Manager.assert_called_once_with(state) |
1139 | + self.script.Manager.return_value.do.assert_called_once_with( |
1140 | 'checkstatus', 'validate', 'diff', 'checkupload', 'ackaging') |
1141 | self.assertEqual(state.status, 'Publishing.') |
1142 | self.script.check_versions_at_destination.assert_called_once_with( |
1143 | @@ -468,7 +468,7 @@ |
1144 | self.mock_main() |
1145 | state = self.script.SiloState() |
1146 | state.status = 'Preserved' |
1147 | - self.script.MergeManager.return_value.do = Mock( |
1148 | + self.script.Manager.return_value.do = Mock( |
1149 | side_effect=NoStatusError('Whoops')) |
1150 | self.assertEqual(self.script.main(), 1) |
1151 | self.assertEqual(state.status, 'Preserved') |
1152 | |
1153 | === modified file 'tests/unit/test_utils.py' |
1154 | --- tests/unit/test_utils.py 2015-09-22 06:53:49 +0000 |
1155 | +++ tests/unit/test_utils.py 2015-09-24 07:13:28 +0000 |
1156 | @@ -25,7 +25,6 @@ |
1157 | SILO_DIR, |
1158 | call, |
1159 | env, |
1160 | - find_all_uploaded, |
1161 | log_call, |
1162 | name_ppa, |
1163 | run_script, |
1164 | @@ -48,28 +47,6 @@ |
1165 | ppa.name = 'foo-ppa' |
1166 | self.assertEqual(name_ppa(ppa), 'foo-team/ubuntu/foo-ppa') |
1167 | |
1168 | - @patch('cupstream2distro.utils.glob') |
1169 | - def test_find_all_uploaded(self, glob_mock): |
1170 | - """Find everything that has been uploaded from this silo.""" |
1171 | - glob_mock.return_value = [ |
1172 | - '/path/to/foo_0.1_source.ppa.upload', |
1173 | - '/path/to/bar_0.2_source.ppa.upload', |
1174 | - ] |
1175 | - self.assertEqual(sorted(find_all_uploaded()), ['bar', 'foo']) |
1176 | - |
1177 | - @patch('cupstream2distro.utils.glob') |
1178 | - def test_find_all_uploaded_multiple_series(self, glob_mock): |
1179 | - """We can handle uploading multiple series from a single silo.""" |
1180 | - glob_mock.return_value = [ |
1181 | - '/path/to/foo_0.1_source.ppa.upload', |
1182 | - '/path/to/foo_0.1~utopic_source.ppa.upload', |
1183 | - '/path/to/bar_0.2_source.ppa.upload', |
1184 | - '/path/to/bar_0.2~utopic_source.ppa.upload', |
1185 | - ] |
1186 | - self.assertEqual(sorted(find_all_uploaded()), |
1187 | - ['bar', 'bar', 'foo', 'foo']) |
1188 | - self.assertEqual(set(find_all_uploaded()), set(['foo', 'bar'])) |
1189 | - |
1190 | @patch('cupstream2distro.utils.logging') |
1191 | def test_env_init(self, log_mock): |
1192 | """Log environment variables when debugging enabled.""" |
Build job is looking good in staging, need to double check that I haven't broken publish or merge, also I haven't updated the tests to the new classes yet.