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
=== modified file 'cidirector/start_builds.py'
--- cidirector/start_builds.py 2016-08-29 15:46:53 +0000
+++ cidirector/start_builds.py 2016-08-29 19:15:51 +0000
@@ -174,9 +174,9 @@
174 for job, job_data in sorted(jobs.items()):174 for job, job_data in sorted(jobs.items()):
175 artifact_job = ArtifactJob(job, logger)175 artifact_job = ArtifactJob(job, logger)
176 for build_info in job_data['builds'].values():176 for build_info in job_data['builds'].values():
177 if build_info['result'] is None:177 if build_info['building']:
178 logger.info(178 logger.debug(
179 'No result for {} #{}. Skipping.'.format(179 'Still building {} #{}. Skipping.'.format(
180 job, build_info['number']))180 job, build_info['number']))
181 continue181 continue
182 logger.info(182 logger.info(
183183
=== modified file 'cidirector/tests/test_start_builds.py'
--- cidirector/tests/test_start_builds.py 2016-08-02 19:39:07 +0000
+++ cidirector/tests/test_start_builds.py 2016-08-29 19:15:51 +0000
@@ -209,9 +209,9 @@
209209
210 @staticmethod210 @staticmethod
211 def make_by_revision_build():211 def make_by_revision_build():
212 build_110 = {'result': 'bar', 'number': 110}212 build_110 = {'building': False, 'result': 'bar', 'number': 110}
213 build_111 = {'result': 'qux', 'number': 111}213 build_111 = {'building': False, 'result': 'qux', 'number': 111}
214 build_120 = {'result': 'baz', 'number': 120}214 build_120 = {'building': False, 'result': 'baz', 'number': 120}
215 return OrderedDict([215 return OrderedDict([
216 ('7081', {'foo': {'builds': {120: build_120}}}),216 ('7081', {'foo': {'builds': {120: build_120}}}),
217 ('7021', {'bar': {'builds': OrderedDict([217 ('7021', {'bar': {'builds': OrderedDict([
@@ -313,9 +313,10 @@
313 '7021', sb.storage),313 '7021', sb.storage),
314 ], aj_instance_mock.archive_results.mock_calls)314 ], aj_instance_mock.archive_results.mock_calls)
315315
316 def test_upload_artifacts_null_result(self):316 def test_upload_artifacts_still_building(self):
317 by_revision = self.make_by_revision_build()317 by_revision = self.make_by_revision_build()
318 by_revision['7021']['bar']['builds'][111]['result'] = None318 by_revision['7081']['foo']['builds'][120]['building'] = True
319 by_revision['7021']['bar']['builds'][110]['building'] = True
319 aj_instance_mock = Mock(spec=['archive_results'])320 aj_instance_mock = Mock(spec=['archive_results'])
320 sb = self.make_start_builds()321 sb = self.make_start_builds()
321 with self.artifact_job_cxt(aj_instance_mock) as aj_mock:322 with self.artifact_job_cxt(aj_instance_mock) as aj_mock:
@@ -325,9 +326,7 @@
325 call('bar', logging.getLogger()),326 call('bar', logging.getLogger()),
326 ], aj_mock.call_args_list)327 ], aj_mock.call_args_list)
327 self.assertEqual([328 self.assertEqual([
328 call(sb.jenkins, by_revision['7081']['foo']['builds'][120],329 call(sb.jenkins, by_revision['7021']['bar']['builds'][111],
329 '7081', sb.storage),
330 call(sb.jenkins, by_revision['7021']['bar']['builds'][110],
331 '7021', sb.storage),330 '7021', sb.storage),
332 ], aj_instance_mock.archive_results.mock_calls)331 ], aj_instance_mock.archive_results.mock_calls)
333332
334333
=== modified file 'cidirector/tests/test_update_outcome.py'
--- cidirector/tests/test_update_outcome.py 2016-08-03 14:48:57 +0000
+++ cidirector/tests/test_update_outcome.py 2016-08-29 19:15:51 +0000
@@ -539,13 +539,32 @@
539 job = OutcomeJob.from_json('foo', {539 job = OutcomeJob.from_json('foo', {
540 'config': {},540 'config': {},
541 'builds': {'1': {541 'builds': {'1': {
542 'building': True,542 'building': False,
543 'number': 1,543 'number': 1,
544 'result': SUCCESS,544 'result': SUCCESS,
545 }},545 }},
546 }, True)546 }, True)
547 self.assertEqual(SUCCEEDED, job.status)547 self.assertEqual(SUCCEEDED, job.status)
548548
549 def test_from_json_building_succeeded(self):
550 job = OutcomeJob.from_json('foo', {
551 'config': {},
552 'builds': {
553 '1': {'building': True, 'number': 1, 'result': SUCCESS}
554 },
555 }, True)
556 self.assertEqual(BUILDING, job.status)
557
558 def test_from_json_building_after_succeeded(self):
559 job = OutcomeJob.from_json('foo', {
560 'config': {},
561 'builds': {
562 '1': {'building': False, 'number': 1, 'result': SUCCESS},
563 '2': {'building': True, 'number': 1, 'result': SUCCESS},
564 },
565 }, True)
566 self.assertEqual(SUCCEEDED, job.status)
567
549 def test_from_json_failed(self):568 def test_from_json_failed(self):
550 job = OutcomeJob.from_json('foo', {569 job = OutcomeJob.from_json('foo', {
551 'config': {},570 'config': {},
552571
=== modified file 'cidirector/update_outcome.py'
--- cidirector/update_outcome.py 2016-08-29 15:46:53 +0000
+++ cidirector/update_outcome.py 2016-08-29 19:15:51 +0000
@@ -267,12 +267,19 @@
267 conflicts = set(config.get('conflicts', '').split())267 conflicts = set(config.get('conflicts', '').split())
268 for build in json['builds'].values():268 for build in json['builds'].values():
269 build_numbers.append(build['number'])269 build_numbers.append(build['number'])
270 # A build may get a result before building is done. i.e.
271 # archiving artifacts happens while a result is set, but before
272 # building is complete. Presumably a failure archiving artifacts
273 # would change the result, so it's not a final result until
274 # building is False.
270 if build['building']:275 if build['building']:
271 building = True276 building = True
272 if build.get('result') == SUCCESS:277 elif build.get('result') == SUCCESS:
273 succeeded = True278 succeeded = True
274 if build.get('result') == FAILURE:279 elif build.get('result') == FAILURE:
275 failure_count += 1280 failure_count += 1
281 # A final success overrides BUILDING; once you have succeeded, future
282 # builds can't change that to BUILDING status.
276 if succeeded:283 if succeeded:
277 status = SUCCEEDED284 status = SUCCEEDED
278 elif building:285 elif building:

Subscribers

People subscribed via source and target branches