diff --git a/tests/fixtures/layouts/provides-requires-single-project.yaml b/tests/fixtures/layouts/provides-requires-single-project.yaml new file mode 100644 index 0000000000..61dd5acbee --- /dev/null +++ b/tests/fixtures/layouts/provides-requires-single-project.yaml @@ -0,0 +1,42 @@ +- pipeline: + name: check + manager: independent + trigger: + gerrit: + - event: patchset-created + success: + gerrit: + Verified: 1 + resultsdb_mysql: null + resultsdb_postgresql: null + failure: + gerrit: + Verified: -1 + resultsdb_mysql: null + resultsdb_postgresql: null + +- job: + name: base + parent: null + run: playbooks/base.yaml + +- job: + name: image-builder + provides: images + +- job: + name: image-user + requires: images + dependencies: + - image-builder + +- job: + name: hold + +- project: + name: org/project1 + check: + jobs: + - image-builder + - image-user + - hold diff --git a/tests/unit/test_v3.py b/tests/unit/test_v3.py index aa8a06c8b1..444d026c01 100644 --- a/tests/unit/test_v3.py +++ b/tests/unit/test_v3.py @@ -5836,8 +5836,39 @@ class TestProvidesRequires(ZuulDBTestCase): dict(name='hold', result='SUCCESS', changes='1,1'), dict(name='hold', result='SUCCESS', changes='1,1 2,1'), ], ordered=False) - self.assertIn('image-user : FAILED', B.messages[0]) - self.assertIn('not met by build', B.messages[0]) + self.assertIn('image-user : FAILURE', B.messages[0]) + self.assertEqual(B.messages[0].count("not met by build"), 2) + + @simple_layout('layouts/provides-requires-single-project.yaml') + def test_provides_requires_check_old_failure_single_project(self): + # Similar to above test, but has job dependencies which will + # cause the requirements check to potentially run multiple + # times as the queue processor runs repeatedly. + A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A') + self.executor_server.failJob('image-builder', A) + self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1)) + self.waitUntilSettled() + + self.assertHistory([ + dict(name='image-builder', result='FAILURE', changes='1,1'), + dict(name='hold', result='SUCCESS', changes='1,1'), + ], ordered=False) + self.assertIn('image-user : SKIPPED', A.messages[0]) + + B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B') + B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % ( + B.subject, A.data['id']) + self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1)) + self.waitUntilSettled() + + self.assertHistory([ + dict(name='image-builder', result='FAILURE', changes='1,1'), + dict(name='hold', result='SUCCESS', changes='1,1'), + dict(name='image-builder', result='FAILURE', changes='1,1 2,1'), + dict(name='hold', result='SUCCESS', changes='1,1 2,1'), + ], ordered=False) + self.assertIn('image-user : FAILURE', B.messages[0]) + self.assertEqual(B.messages[0].count("not met by build"), 1) class TestForceMergeMissingTemplate(ZuulTestCase): diff --git a/zuul/model.py b/zuul/model.py index 575b50b6d1..29679bd9f4 100644 --- a/zuul/model.py +++ b/zuul/model.py @@ -2382,7 +2382,7 @@ class QueueItem(object): except RequirementsError as e: self.warning(str(e)) fakebuild = Build(job, None) - fakebuild.result = 'FAILED' + fakebuild.result = 'FAILURE' self.addBuild(fakebuild) ret = True return ret @@ -2466,7 +2466,7 @@ class QueueItem(object): build = build_set.getBuild(job.name) if build and (build.result == 'SUCCESS' or build.paused): successful_job_names.add(job.name) - elif build and build.result == 'SKIPPED': + elif build and build.result in ('SKIPPED', 'FAILURE'): pass else: nodeset = build_set.getJobNodeSet(job.name)