Using Jenkins Job-DSL Configure block to place custom steps in particular positions
groovy, jenkins, jenkins-job-dsl
Solution
You can use the `<<` operator to append nodes, otherwise an existing node with an identical name gets replaced. See the Job DSL wiki for details.
job {
name('foo')
steps {
shell('echo AAA')
}
configure {
it / builders << 'hudson.plugins.xshell.XShellBuilder' {
commandLine('123')
}
}
steps {
shell('echo BBB')
}
configure {
it / builders << 'hudson.plugins.xshell.XShellBuilder' {
commandLine('456')
}
}
}
Problem
Using the job-dsl-plugin I am attempting to script the configuration of a fair number of Jenkins jobs which have previously been configured manually. One flavour of these jobs has multiple steps including a couple which use the XShell plugin, this is not directly supported by job-dsl. However I should be able to get around that by using a custom "configure" block. Using the "Job DSL playground" at http://job-dsl.herokuapp.com/ I've got as far as: ``` job { name 'my-job' jdk('JDK-17') steps { configure { node -> node / builders { 'hudson.plugins.xshell.XShellBuilder'(plugin: 'xshell@0.9') { commandLine('run-me-as-the-first-build-step') executeFromWorkingDir('true') } } } maven { mavenInstallation('Default') goals('clean') goals('verify') property('prop1', 'value1') property('user.timezone', 'UTC') mavenOpts('--batch-mode') } maven { mavenInstallation('Default') goals('deploy') property('prop2', 'value2') property('user.timezone', 'UTC') mavenOpts('--batch-mode') } shell('shell-task') configure { node -> node / builders { 'hudson.plugins.xshell.XShellBuilder'(plugin: 'xshell@0.9') { commandLine('run-me-as-the-last-build-step') executeFromWorkingDir('true') } } } } } ``` If I just include the first configure block only, I do get the first command at the first step position. But with the second (last) configure block present, the `"node / builders"` is matching on the first element again and overwriting it, so `run-me-as-the-last-step` is the first and only XShellBuilder. The output I seek would look something like: ``` <project> ... <builders> <hudson.plugins.xshell.XShellBuilder plugin='xshell@0.9'> <commandLine>run-me-as-the-first-build-step</commandLine> <executeFromWorkingDir>true</executeFromWorkingDir> </hudson.plugins.xshell.XShellBuilder> <hudson.tasks.Maven> <targets>clean verify</targets> <properties>prop1=value1 user.timezone=UTC</properties> <mavenName>Default</mavenName> <jvmOptions>--batch-mode</jvmOptions> <usePrivateRepository>false</usePrivateRepository> </hudson.tasks.Maven> <hudson.tasks.Maven> <targets>deploy</targets> <properties>prop2=value2 user.timezone=UTC</properties> <mavenName>Default</mavenName> <jvmOptions>--batch-mode</jvmOptions> <usePrivateRepository>false</usePrivateRepository> </hudson.tasks.Maven> <hudson.tasks.Shell> <command>shell-task</command> </hudson.tasks.Shell> <hudson.plugins.xshell.XShellBuilder plugin='xshell@0.9'> <commandLine>run-me-as-the-last-build-step</commandLine> <executeFromWorkingDir>true</executeFromWorkingDir> </hudson.plugins.xshell.XShellBuilder> </builders> ... </project> ``` I can't figure out the Groovy XML / Job-DSL syntax to insert that second block as "last child; can a Job-DSL or Groovy XMLParser expert please give me a pointer on how to match and insert at an arbitrary position in the children of `<builders>`? (I appreciate that I could use `job(type:Maven)` with `preBuildSteps` and `postBuildSteps` but actually I need a few other things in there as well which a pure maven job precludes.) Thanks!