Enable job-specific substitutions in a project's job list.

The motivation for this was to allow for specifying a pipeline of jobs
at the project level, thereby re-using the same job templates in
different pipelines.

Change-Id: I9840d3713669ceca75a831be92c95c3fe9195c01
This commit is contained in:
Manuel Desbonnet 2012-09-26 12:49:50 +01:00
parent 7dd198eff8
commit 67016c3452
2 changed files with 47 additions and 6 deletions

View File

@ -90,6 +90,17 @@ template. Any job templates listed under ``jobs:`` will be realized
with those values. The example above would create the job called
'project-name-unit-tests' in Jenkins.
The ``jobs:`` list can also allow for specifying job-specific
substitutions as follows::
- project:
name: project-name
jobs:
- {name}-unit-tests:
mail-to: developer@nowhere.net
- {name}-perf-tests:
mail-to: projmanager@nowhere.net
Job Group
^^^^^^^^^

View File

@ -28,6 +28,28 @@ import logging
logger = logging.getLogger(__name__)
def deep_format(obj, paramdict):
"""Apply the paramdict via str.format() to all string objects found within
the supplied obj. Lists and dicts are traversed recursively."""
# YAML serialisation was originally used to achieve this, but that places
# limitations on the values in paramdict - the post-format result must
# still be valid YAML (so substituting-in a string containing quotes, for
# example, is problematic).
if isinstance(obj, str):
ret = obj.format(**paramdict)
elif isinstance(obj, list):
ret = []
for item in obj:
ret.append(deep_format(item, paramdict))
elif isinstance(obj, dict):
ret = {}
for item in obj:
ret[item] = deep_format(obj[item], paramdict)
else:
ret = obj
return ret
class YamlParser(object):
def __init__(self, config=None):
self.registry = ModuleRegistry(config)
@ -81,7 +103,13 @@ class YamlParser(object):
self.getXMLForJob(job)
for project in self.data.get('project', {}).values():
logger.debug("XMLifying project '{0}'".format(project['name']))
for jobname in project.get('jobs', []):
for jobspec in project.get('jobs', []):
if isinstance(jobspec, dict):
# Singleton dict containing dict of job-specific params
jobname, jobparams = jobspec.items()[0]
else:
jobname = jobspec
jobparams = {}
job = self.getJob(jobname)
if job:
# Just naming an existing defined job
@ -106,13 +134,15 @@ class YamlParser(object):
# see if it's a template
template = self.getJobTemplate(jobname)
if template:
self.getXMLForTemplateJob(project, template)
params = dict(project)
params.update(deep_format(jobparams, project))
logger.debug("Generating XML for template job {0}"
" (params {1})".format(
template['name'], params))
self.getXMLForTemplateJob(params, template)
def getXMLForTemplateJob(self, project, template):
s = yaml.dump(template, default_flow_style=False)
s = s.format(**project)
data = yaml.load(s)
self.getXMLForJob(data)
self.getXMLForJob(deep_format(template, project))
def getXMLForJob(self, data):
kind = data.get('project-type', 'freestyle')