Merge lp:~abentley/ci-director/building-trumps-result into lp:ci-director

Proposed by Aaron Bentley
Status: Merged
Merged at revision: 184
Proposed branch: lp:~abentley/ci-director/building-trumps-result
Merge into: lp:ci-director
Diff against target: 121 lines (+39/-14)
4 files modified
cidirector/start_builds.py (+3/-3)
cidirector/tests/test_start_builds.py (+7/-8)
cidirector/tests/test_update_outcome.py (+20/-1)
cidirector/update_outcome.py (+9/-2)
To merge this branch: bzr merge lp:~abentley/ci-director/building-trumps-result
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+304287@code.launchpad.net

Commit message

Results are not final until building is false.

Description of the change

This branch changes build results to be non-final until building is done.

There are two problems revealed by the s390x issue
- Premature uploads of a build / repeated uploads of a build.
- Premature triggering of dependant jobs.

The first issue is fixed by using 'building' instead of 'result' to determine whether to upload.

The second issue is fixed in OutcomeJob.from_json, by using 'building' to override 'result' for an indivdual build.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

thank you.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cidirector/start_builds.py'
2--- cidirector/start_builds.py 2016-08-29 15:46:53 +0000
3+++ cidirector/start_builds.py 2016-08-29 19:15:51 +0000
4@@ -174,9 +174,9 @@
5 for job, job_data in sorted(jobs.items()):
6 artifact_job = ArtifactJob(job, logger)
7 for build_info in job_data['builds'].values():
8- if build_info['result'] is None:
9- logger.info(
10- 'No result for {} #{}. Skipping.'.format(
11+ if build_info['building']:
12+ logger.debug(
13+ 'Still building {} #{}. Skipping.'.format(
14 job, build_info['number']))
15 continue
16 logger.info(
17
18=== modified file 'cidirector/tests/test_start_builds.py'
19--- cidirector/tests/test_start_builds.py 2016-08-02 19:39:07 +0000
20+++ cidirector/tests/test_start_builds.py 2016-08-29 19:15:51 +0000
21@@ -209,9 +209,9 @@
22
23 @staticmethod
24 def make_by_revision_build():
25- build_110 = {'result': 'bar', 'number': 110}
26- build_111 = {'result': 'qux', 'number': 111}
27- build_120 = {'result': 'baz', 'number': 120}
28+ build_110 = {'building': False, 'result': 'bar', 'number': 110}
29+ build_111 = {'building': False, 'result': 'qux', 'number': 111}
30+ build_120 = {'building': False, 'result': 'baz', 'number': 120}
31 return OrderedDict([
32 ('7081', {'foo': {'builds': {120: build_120}}}),
33 ('7021', {'bar': {'builds': OrderedDict([
34@@ -313,9 +313,10 @@
35 '7021', sb.storage),
36 ], aj_instance_mock.archive_results.mock_calls)
37
38- def test_upload_artifacts_null_result(self):
39+ def test_upload_artifacts_still_building(self):
40 by_revision = self.make_by_revision_build()
41- by_revision['7021']['bar']['builds'][111]['result'] = None
42+ by_revision['7081']['foo']['builds'][120]['building'] = True
43+ by_revision['7021']['bar']['builds'][110]['building'] = True
44 aj_instance_mock = Mock(spec=['archive_results'])
45 sb = self.make_start_builds()
46 with self.artifact_job_cxt(aj_instance_mock) as aj_mock:
47@@ -325,9 +326,7 @@
48 call('bar', logging.getLogger()),
49 ], aj_mock.call_args_list)
50 self.assertEqual([
51- call(sb.jenkins, by_revision['7081']['foo']['builds'][120],
52- '7081', sb.storage),
53- call(sb.jenkins, by_revision['7021']['bar']['builds'][110],
54+ call(sb.jenkins, by_revision['7021']['bar']['builds'][111],
55 '7021', sb.storage),
56 ], aj_instance_mock.archive_results.mock_calls)
57
58
59=== modified file 'cidirector/tests/test_update_outcome.py'
60--- cidirector/tests/test_update_outcome.py 2016-08-03 14:48:57 +0000
61+++ cidirector/tests/test_update_outcome.py 2016-08-29 19:15:51 +0000
62@@ -539,13 +539,32 @@
63 job = OutcomeJob.from_json('foo', {
64 'config': {},
65 'builds': {'1': {
66- 'building': True,
67+ 'building': False,
68 'number': 1,
69 'result': SUCCESS,
70 }},
71 }, True)
72 self.assertEqual(SUCCEEDED, job.status)
73
74+ def test_from_json_building_succeeded(self):
75+ job = OutcomeJob.from_json('foo', {
76+ 'config': {},
77+ 'builds': {
78+ '1': {'building': True, 'number': 1, 'result': SUCCESS}
79+ },
80+ }, True)
81+ self.assertEqual(BUILDING, job.status)
82+
83+ def test_from_json_building_after_succeeded(self):
84+ job = OutcomeJob.from_json('foo', {
85+ 'config': {},
86+ 'builds': {
87+ '1': {'building': False, 'number': 1, 'result': SUCCESS},
88+ '2': {'building': True, 'number': 1, 'result': SUCCESS},
89+ },
90+ }, True)
91+ self.assertEqual(SUCCEEDED, job.status)
92+
93 def test_from_json_failed(self):
94 job = OutcomeJob.from_json('foo', {
95 'config': {},
96
97=== modified file 'cidirector/update_outcome.py'
98--- cidirector/update_outcome.py 2016-08-29 15:46:53 +0000
99+++ cidirector/update_outcome.py 2016-08-29 19:15:51 +0000
100@@ -267,12 +267,19 @@
101 conflicts = set(config.get('conflicts', '').split())
102 for build in json['builds'].values():
103 build_numbers.append(build['number'])
104+ # A build may get a result before building is done. i.e.
105+ # archiving artifacts happens while a result is set, but before
106+ # building is complete. Presumably a failure archiving artifacts
107+ # would change the result, so it's not a final result until
108+ # building is False.
109 if build['building']:
110 building = True
111- if build.get('result') == SUCCESS:
112+ elif build.get('result') == SUCCESS:
113 succeeded = True
114- if build.get('result') == FAILURE:
115+ elif build.get('result') == FAILURE:
116 failure_count += 1
117+ # A final success overrides BUILDING; once you have succeeded, future
118+ # builds can't change that to BUILDING status.
119 if succeeded:
120 status = SUCCEEDED
121 elif building:

Subscribers

People subscribed via source and target branches