diff --git a/doc/source/definition.rst b/doc/source/definition.rst index 848f7198b..dc04ab680 100644 --- a/doc/source/definition.rst +++ b/doc/source/definition.rst @@ -261,6 +261,14 @@ For example: .. literalinclude:: /../../tests/yamlparser/fixtures/yaml_anchor.yaml +JJB also supports interpolation of parameters within parameters. This allows a +little more flexibility when ordering template jobs as components in different +projects and job groups. + +For example: + +.. literalinclude:: /../../tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml + Custom Yaml Tags ---------------- diff --git a/jenkins_jobs/builder.py b/jenkins_jobs/builder.py index 2b006ea7a..280b70b11 100644 --- a/jenkins_jobs/builder.py +++ b/jenkins_jobs/builder.py @@ -209,12 +209,21 @@ class YamlParser(object): return job return self.applyDefaults(job) - def applyDefaults(self, data): + def applyDefaults(self, data, override_dict=None): + if override_dict is None: + override_dict = {} + whichdefaults = data.get('defaults', 'global') - defaults = self.data.get('defaults', {}).get(whichdefaults, {}) + defaults = copy.deepcopy(self.data.get('defaults', + {}).get(whichdefaults, {})) if defaults == {} and whichdefaults != 'global': raise JenkinsJobsException("Unknown defaults set: '{0}'" .format(whichdefaults)) + + for key in override_dict.keys(): + if key in defaults.keys(): + defaults[key] = override_dict[key] + newdata = {} newdata.update(defaults) newdata.update(data) @@ -325,8 +334,11 @@ class YamlParser(object): def expandYamlForTemplateJob(self, project, template, jobs_filter=None): dimensions = [] + # reject keys that are not useful during yaml expansion + for k in ['jobs']: + project.pop(k) for (k, v) in project.items(): - if type(v) == list and k not in ['jobs']: + if type(v) == list: dimensions.append(zip([k] * len(v), v)) # XXX somewhat hackish to ensure we actually have a single # pass through the loop @@ -335,7 +347,7 @@ class YamlParser(object): checksums = set([]) for values in itertools.product(*dimensions): params = copy.deepcopy(project) - params = self.applyDefaults(params) + params = self.applyDefaults(params, template) expanded_values = {} for (k, v) in values: @@ -347,6 +359,7 @@ class YamlParser(object): expanded_values[k] = v params.update(expanded_values) + params = deep_format(params, params) expanded = deep_format(template, params) # Keep track of the resulting expansions to avoid diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation001.xml b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.xml new file mode 100644 index 000000000..75c2046cc --- /dev/null +++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.xml @@ -0,0 +1,16 @@ + + + + <!-- Managed by Jenkins Job Builder --> + false + experimental_foo + false + false + false + true + + + + + + diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation001.yaml b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.yaml new file mode 100644 index 000000000..c7fc1a56b --- /dev/null +++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation001.yaml @@ -0,0 +1,13 @@ +- job-template: + name: '{value-stream}_{pipeline-type}' + display-name: '{value-stream}_{pipeline-type}' + +- project: + name: derp + jobs: + - '{value-stream}_{pipeline-type}': + pipeline-type: 'foo' + +- defaults: + name: 'global' + value-stream: 'experimental' diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation002.xml b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.xml new file mode 100644 index 000000000..bdab430fe --- /dev/null +++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.xml @@ -0,0 +1,127 @@ + + + + <!-- Managed by Jenkins Job Builder --> + false + experimental p2 bar + false + false + false + true + + + + + + + + + + false + + + + ALWAYS + false + + + + + + + + + + + <!-- Managed by Jenkins Job Builder --> + false + experimental p2 foo + false + false + false + true + + + + + + + + + + false + + + experimental_p2_bar + ALWAYS + false + + + + + + + + + + + <!-- Managed by Jenkins Job Builder --> + false + production p1 bar + false + false + false + true + + + + + + + + + + false + + + production_p1_foo + ALWAYS + false + + + + + + + + + + + <!-- Managed by Jenkins Job Builder --> + false + production p1 foo + false + false + false + true + + + + + + + + + + false + + + + ALWAYS + false + + + + + + diff --git a/tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml new file mode 100644 index 000000000..380fbd9aa --- /dev/null +++ b/tests/yamlparser/fixtures/second_order_parameter_interpolation002.yaml @@ -0,0 +1,47 @@ +- job-template: + name: '{value-stream}_{project-id}_foo' + display-name: '{value-stream} {project-id} foo' + publishers: + - trigger-parameterized-builds: + - project: '{downstream}' + current-parameters: False + condition: ALWAYS + git-revision: True + +- job-template: + name: '{value-stream}_{project-id}_bar' + display-name: '{value-stream} {project-id} bar' + publishers: + - trigger-parameterized-builds: + - project: '{downstream}' + current-parameters: False + condition: ALWAYS + git-revision: True + +- job-group: + name: 'pipeline2' + project-id: 'p2' + jobs: + - '{value-stream}_{project-id}_foo': + downstream: '{value-stream}_{project-id}_bar' + - '{value-stream}_{project-id}_bar': + +- job-group: + name: 'pipeline1' + project-id: 'p1' + jobs: + - '{value-stream}_{project-id}_bar': + downstream: '{value-stream}_{project-id}_foo' + - '{value-stream}_{project-id}_foo': + +- project: + name: derp + jobs: + - 'pipeline1': + value-stream: 'production' + - 'pipeline2': + value-stream: 'experimental' + +- defaults: + name: 'global' + downstream: ''