Support zuul.child_jobs via zuul_return
Expose the ability for a user to skip child jobs using zuul_return and zuul.child_jobs. Change-Id: I21ea9b2d3b1711f0d55bbe3d626ac7dde5db2919 Signed-off-by: Paul Belanger <pabelanger@redhat.com>
This commit is contained in:
parent
144df5e2d5
commit
5c797a12a8
|
@ -580,6 +580,25 @@ To set the log URL for a build, use *zuul_return* to set the
|
|||
zuul:
|
||||
log_url: http://logs.example.com/path/to/build/logs
|
||||
|
||||
To skip a child job for the current build, use *zuul_return* to set the
|
||||
:var:`zuul.child_jobs` value. For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
tasks:
|
||||
- zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
child_jobs:
|
||||
- child_jobA
|
||||
- child_jobC
|
||||
|
||||
Will tell zuul to only run the child_jobA and child_jobC for pre-configured
|
||||
child jobs. If child_jobB was configured, it would be now marked as SKIPPED. If
|
||||
zuul.child_jobs is empty, all jobs will be marked as SKIPPED. Invalid child jobs
|
||||
are stripped and ignored, if only invalid jobs are listed it is the same as
|
||||
providing an empty list to zuul.child_jobs.
|
||||
|
||||
Any values other than those in the ``zuul`` hierarchy will be supplied
|
||||
as Ansible variables to child jobs. These variables have less
|
||||
precedence than any other type of variable in Zuul, so be sure their
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
It is now possible to use zuul_return to skip child jobs. You can
|
||||
use the :var:`zuul.child_jobs` inventory variable to get a list of
|
||||
child jobs configured to run, then use zuul_return to modify the
|
||||
list. Any child job not in zuul_return zuul.child_jobs will be
|
||||
skipped. See :ref:`return_values` for examples.
|
8
tests/fixtures/config/data-return/git/common-config/playbooks/data-return-child-jobs.yaml
vendored
Normal file
8
tests/fixtures/config/data-return/git/common-config/playbooks/data-return-child-jobs.yaml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
- hosts: localhost
|
||||
tasks:
|
||||
- zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
child_jobs:
|
||||
- data-return
|
||||
log_url: http://example.com/test/log/url/
|
|
@ -0,0 +1,8 @@
|
|||
- hosts: localhost
|
||||
tasks:
|
||||
- zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
child_jobs:
|
||||
- invalid-job
|
||||
log_url: http://example.com/test/log/url/
|
7
tests/fixtures/config/data-return/git/common-config/playbooks/data-return-skip-all.yaml
vendored
Normal file
7
tests/fixtures/config/data-return/git/common-config/playbooks/data-return-skip-all.yaml
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
- hosts: localhost
|
||||
tasks:
|
||||
- zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
child_jobs: []
|
||||
log_url: http://example.com/test/log/url/
|
|
@ -20,6 +20,18 @@
|
|||
name: data-return
|
||||
run: playbooks/data-return.yaml
|
||||
|
||||
- job:
|
||||
name: data-return-child-jobs
|
||||
run: playbooks/data-return-child-jobs.yaml
|
||||
|
||||
- job:
|
||||
name: data-return-invalid-child-job
|
||||
run: playbooks/data-return-invalid-child-job.yaml
|
||||
|
||||
- job:
|
||||
name: data-return-skip-all
|
||||
run: playbooks/data-return-skip-all.yaml
|
||||
|
||||
- job:
|
||||
name: data-return-relative
|
||||
success-url: docs/index.html
|
||||
|
@ -39,3 +51,36 @@
|
|||
dependencies:
|
||||
- data-return
|
||||
- data-return-relative
|
||||
|
||||
- project:
|
||||
name: org/project1
|
||||
check:
|
||||
jobs:
|
||||
- data-return-child-jobs
|
||||
- data-return:
|
||||
dependencies:
|
||||
- data-return-child-jobs
|
||||
- child:
|
||||
dependencies:
|
||||
- data-return-child-jobs
|
||||
|
||||
- project:
|
||||
name: org/project2
|
||||
check:
|
||||
jobs:
|
||||
- data-return-invalid-child-job
|
||||
- data-return:
|
||||
dependencies:
|
||||
- data-return-invalid-child-job
|
||||
|
||||
- project:
|
||||
name: org/project3
|
||||
check:
|
||||
jobs:
|
||||
- data-return-skip-all
|
||||
- data-return:
|
||||
dependencies:
|
||||
- data-return-skip-all
|
||||
- child:
|
||||
dependencies:
|
||||
- data-return-skip-all
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
test
|
|
@ -0,0 +1 @@
|
|||
test
|
|
@ -0,0 +1 @@
|
|||
test
|
|
@ -6,3 +6,6 @@
|
|||
- common-config
|
||||
untrusted-projects:
|
||||
- org/project
|
||||
- org/project1
|
||||
- org/project2
|
||||
- org/project3
|
||||
|
|
|
@ -2827,6 +2827,52 @@ class TestDataReturn(AnsibleZuulTestCase):
|
|||
'http://example.com/test/log/url/docs/index.html',
|
||||
A.messages[-1])
|
||||
|
||||
def test_data_return_child_jobs(self):
|
||||
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertHistory([
|
||||
dict(name='data-return-child-jobs', result='SUCCESS',
|
||||
changes='1,1'),
|
||||
dict(name='data-return', result='SUCCESS', changes='1,1'),
|
||||
])
|
||||
self.assertIn(
|
||||
'- data-return-child-jobs http://example.com/test/log/url/',
|
||||
A.messages[-1])
|
||||
self.assertIn(
|
||||
'- data-return http://example.com/test/log/url/',
|
||||
A.messages[-1])
|
||||
self.assertIn('child : SKIPPED', A.messages[-1])
|
||||
self.assertIn('Build succeeded', A.messages[-1])
|
||||
|
||||
def test_data_return_invalid_child_job(self):
|
||||
A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertHistory([
|
||||
dict(name='data-return-invalid-child-job', result='SUCCESS',
|
||||
changes='1,1')])
|
||||
self.assertIn(
|
||||
'- data-return-invalid-child-job http://example.com/test/log/url/',
|
||||
A.messages[-1])
|
||||
self.assertIn('data-return : SKIPPED', A.messages[-1])
|
||||
self.assertIn('Build succeeded', A.messages[-1])
|
||||
|
||||
def test_data_return_skip_all_child_jobs(self):
|
||||
A = self.fake_gerrit.addFakeChange('org/project3', 'master', 'A')
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertHistory([
|
||||
dict(name='data-return-skip-all', result='SUCCESS',
|
||||
changes='1,1'),
|
||||
])
|
||||
self.assertIn(
|
||||
'- data-return-skip-all http://example.com/test/log/url/',
|
||||
A.messages[-1])
|
||||
self.assertIn('child : SKIPPED', A.messages[-1])
|
||||
self.assertIn('data-return : SKIPPED', A.messages[-1])
|
||||
self.assertIn('Build succeeded', A.messages[-1])
|
||||
|
||||
|
||||
class TestDiskAccounting(AnsibleZuulTestCase):
|
||||
config_file = 'zuul-disk-accounting.conf'
|
||||
|
|
|
@ -1802,14 +1802,24 @@ class QueueItem(object):
|
|||
def didAllJobsSucceed(self):
|
||||
if not self.hasJobGraph():
|
||||
return False
|
||||
|
||||
skipped = True
|
||||
for job in self.getJobs():
|
||||
if not job.voting:
|
||||
continue
|
||||
build = self.current_build_set.getBuild(job.name)
|
||||
if not build:
|
||||
return False
|
||||
if build.result != 'SUCCESS':
|
||||
if build.result == 'SKIPPED':
|
||||
continue
|
||||
elif build.result != 'SUCCESS':
|
||||
return False
|
||||
skipped = False
|
||||
|
||||
# NOTE(pabelanger): We shouldn't be able to skip all jobs.
|
||||
if skipped:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def didAnyJobFail(self):
|
||||
|
@ -1971,12 +1981,39 @@ class QueueItem(object):
|
|||
def setResult(self, build):
|
||||
if build.retry:
|
||||
self.removeBuild(build)
|
||||
return
|
||||
|
||||
skipped = []
|
||||
# NOTE(pabelanger): Check successful jobs to see if zuul_return
|
||||
# includes zuul.child_jobs.
|
||||
build_result = build.result_data.get('zuul', {})
|
||||
if 'child_jobs' in build_result:
|
||||
zuul_return = build_result.get('child_jobs', [])
|
||||
dependent_jobs = self.job_graph.getDirectDependentJobs(
|
||||
build.job.name)
|
||||
|
||||
if not zuul_return:
|
||||
# If zuul.child_jobs exists and is empty, user want to skip all
|
||||
# child jobs.
|
||||
skipped += self.job_graph.getDependentJobsRecursively(
|
||||
build.job.name)
|
||||
else:
|
||||
# We have list of jobs to run.
|
||||
intersect_jobs = dependent_jobs.intersection(zuul_return)
|
||||
|
||||
for skip in (dependent_jobs - intersect_jobs):
|
||||
skipped.append(self.job_graph.jobs.get(skip))
|
||||
skipped += self.job_graph.getDependentJobsRecursively(
|
||||
skip)
|
||||
|
||||
elif build.result != 'SUCCESS':
|
||||
for job in self.job_graph.getDependentJobsRecursively(
|
||||
build.job.name):
|
||||
fakebuild = Build(job, None)
|
||||
fakebuild.result = 'SKIPPED'
|
||||
self.addBuild(fakebuild)
|
||||
skipped += self.job_graph.getDependentJobsRecursively(
|
||||
build.job.name)
|
||||
|
||||
for job in skipped:
|
||||
fakebuild = Build(job, None)
|
||||
fakebuild.result = 'SKIPPED'
|
||||
self.addBuild(fakebuild)
|
||||
|
||||
def setNodeRequestFailure(self, job):
|
||||
fakebuild = Build(job, None)
|
||||
|
|
Loading…
Reference in New Issue