Forward artifacts to child jobs within buildset

When providing an artifact using zuul_return this information is
currently only available in different changes. However just like
regular variables this information should be forwarded to child jobs
in the same buildset too.

Change-Id: I8fefb57ccbbd61d51f96f18e882c0ab615cb0cd0
This commit is contained in:
Tobias Henkel 2019-03-12 19:39:55 +01:00
parent 1ba690be3d
commit 6d5ecd65ba
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
9 changed files with 124 additions and 2 deletions

View File

@ -0,0 +1,5 @@
---
features:
- |
The :ref:`artifacts <return_artifacts>` returned by parent jobs are now
also available in child jobs of the same buildset.

View File

@ -0,0 +1,17 @@
- pipeline:
name: check
manager: independent
post-review: true
trigger:
gerrit:
- event: patchset-created
success:
gerrit:
Verified: 1
failure:
gerrit:
Verified: -1
- job:
name: base
parent: null

View File

@ -0,0 +1 @@
test

View File

@ -0,0 +1,10 @@
- hosts: all
tasks:
- name: Pause and let child run
zuul_return:
data:
zuul:
pause: true
artifacts:
- name: image
url: http://example.com/image

View File

@ -0,0 +1,4 @@
- hosts: all
tasks:
- debug:
var: zuul.artifacts

View File

@ -0,0 +1,15 @@
- job:
name: image-builder
run: playbooks/image-builder.yaml
- job:
name: image-user
run: playbooks/image-user.yaml
- project:
check:
jobs:
- image-builder
- image-user:
dependencies:
- image-builder

View File

@ -0,0 +1,7 @@
- tenant:
name: tenant-one
source:
gerrit:
config-projects:
- common-config
- org/project1

View File

@ -5009,6 +5009,55 @@ class TestProvidesRequiresPause(AnsibleZuulTestCase):
}])
class TestProvidesRequiresBuildset(ZuulTestCase):
tenant_config_file = "config/provides-requires-buildset/main.yaml"
def test_provides_requires_buildset(self):
# Changes share a queue, with both running at the same time.
self.executor_server.hold_jobs_in_build = True
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
self.executor_server.returnData(
'image-builder', A,
{'zuul':
{'artifacts': [
{'name': 'image',
'url': 'http://example.com/image',
'metadata': {
'type': 'container_image'
}},
]}}
)
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
self.waitUntilSettled()
self.assertEqual(len(self.builds), 1)
self.executor_server.hold_jobs_in_build = False
self.executor_server.release()
self.waitUntilSettled()
self.assertHistory([
dict(name='image-builder', result='SUCCESS', changes='1,1'),
dict(name='image-user', result='SUCCESS', changes='1,1'),
])
build = self.getJobFromHistory('image-user', project='org/project1')
self.assertEqual(
build.parameters['zuul']['artifacts'],
[{
'project': 'org/project1',
'change': '1',
'patchset': '1',
'job': 'image-builder',
'url': 'http://example.com/image',
'name': 'image',
'metadata': {
'type': 'container_image',
}
}])
class TestProvidesRequires(ZuulDBTestCase):
config_file = "zuul-sql-driver.conf"

View File

@ -1393,10 +1393,11 @@ class Job(ConfigObject):
self.group_variables = Job._deepUpdate(
self.group_variables, other_group_vars)
def updateParentData(self, other_vars):
def updateParentData(self, other_build):
# Update variables, but give the current values priority (used
# for job return data which is lower precedence than defined
# job vars).
other_vars = other_build.result_data
v = self.parent_data or {}
v = Job._deepUpdate(v, other_vars)
# To avoid running afoul of checks that jobs don't set zuul
@ -1406,6 +1407,19 @@ class Job(ConfigObject):
self.parent_data = v
self.variables = Job._deepUpdate(self.parent_data, self.variables)
artifact_data = self.artifact_data or []
artifacts = get_artifacts_from_result_data(other_vars)
for a in artifacts:
change = other_build.build_set.item.change
a.update({'project': change.project.name,
'change': str(change.number),
'patchset': change.patchset,
'job': other_build.job.name})
if a not in artifact_data:
artifact_data.append(a)
if artifact_data:
self.updateArtifactData(artifact_data)
def updateArtifactData(self, artifact_data):
self.artifact_data = artifact_data
@ -2404,7 +2418,7 @@ class QueueItem(object):
parent_build = parent_builds_with_data.get(
parent_job.name)
if parent_build:
job.updateParentData(parent_build.result_data)
job.updateParentData(parent_build)
nodeset = self.current_build_set.getJobNodeSet(job.name)
if nodeset is None: