Code your Jenkins jobs with JobDSL

Daniela Kortin
ProdOpsIO
Published in
4 min readJan 19, 2017

Jenkins is a powerful automation platform to run your tests on a non-development machine whenever someone pushes new code into the source repository. It makes life easier. Almost immediate feedback tells you what and who introduced the problem, and you can fix it accordingly. Quite simply, Jenkins makes life easier.

But when it comes to operating Jenkins on the system’s user interface, you have to do it manually. Creating a new item, adding parameters, adding steps, choosing the job subject — you do all these by clicking buttons on the Jenkins UI. When the number of jobs grows, it becomes inconvenient to maintain them using the UI. For instance, if you want to add a general plug-in like Slack to all of your jobs, you will have to modify each job in your project and add the new plug-in, one by one.

If Jenkins crashes or if a user changes, updates, deletes or moves a job, it won’t be easy to reverse the changes. Jenkins saves all the jobs and their settings in XML files. In order to recover jobs, you have to copy and paste those files into the system — a very old-fashioned way to restore things, especially since the establishment of development version control tools. You might also lose data if you defined your hard disk back-up to save things once every day or two.

A cool Jenkins plugin called Job DSL can solve this problem by giving you the opportunity to program your jobs’ building process instead of clicking buttons on the UI. It also enables integration with version control tools like Git, so when a change is made, it will be preserved automatically. It’s pretty easy to restore an older version of your jobs. Using a base template for jobs can save time re-configuring settings, and it helps prevent inaccuracies and conflicts.

So how does it work? First, install or upgrade the Job DSL plugin for the Jenkins version you are using. You can do this as follows:

Jenkins > Manage Jenkins > Manage Plugins > Job DSL

Then, to create a new job for a build, you will have to make the following selection:

Jenkins > New Item > Add Build Step > Process Job DSLs

The template of adding an additional job to DSL script, written in Groovy, looks like this:

def project = 'quidryan/aws-sdk-test'
def branchApi = new URL("https://api.github.com/repos/${project}/branches")
def branches = new groovy.json.JsonSlurper().parse(branchApi.newReader())
branches.each {
def branchName = it.name
def jobName = "${project}-${branchName}".replaceAll('/','-')
job(jobName) {
scm {
git("git://github.com/${project}.git", branchName)
}
steps {
maven("test -Dproject.name=${project}/${branchName}")
}
}
}

All methods that will be needed to write the code according to your requirements — like buildFlowJob(String name), buildMonitorView(String name), buildPipelineView(String name) and more — can be found here.

If you are looking to set up multiple jobs so you can create a full hierarchy of Jenkins jobs that will be executed in sequence or in parallel, you can import the code from here.

The template looks like this:

multiJob('example') {
steps {
phase('Second') {
phaseJob('JobZ') {
parameters {
propertiesFile('my1.properties')
}
}
}
phase('Third') {
phaseJob('JobA')
phaseJob('JobB')
phaseJob('JobC')
}
phase('Fourth') {
phaseJob('JobD') {
currentJobParameters(false)
parameters {
booleanParam('cParam', true)
propertiesFile('my.properties')
sameNode()
matrixSubset('it.name=="hello"')
subversionRevision()
gitRevision()
predefinedProp('prop1', 'value1')
nodeLabel('lParam', 'my_nodes')
}
configure { phaseJobConfig ->
phaseJobConfig / enableCondition << 'true'
phaseJobConfig / condition << '${RUN_JOB} == "true"'
}
}
}
}
}

The jobs in each “phase” will be executed in parallel, and the phases are sequential, meaning the jobs in phase 2 will be executed only after phase 1 jobs are completed.

The Job DSL plugin for Jenkins allows you to create and update job configurations in Jenkins based on source code written in the Groovy language. The basic job declaration structure looks like this:

job(‘example’) {
scm {
git ‘git@om-git.mm.local/project/name.git’
}
triggers {
scm ‘*/15 * * * *’
}
steps {
sbt()
}
}

There are several ways to reuse code when using the Jenkins Job DSL plug-in:

  1. Use a template that declares a job, and multiple jobs can inherit this template. Every change to the template job will also propagate to other jobs that use it.

Example:

job(‘tmpl_base’) {
disabled true
logRotator –1, 10, –1, –1
}
job(‘real_job’) {
using ‘tmpl_base’
disabled false
steps {
shell ‘echo Rotates just like the template!’
}
}
  1. Use the Groovy language to create more than one job using a loop or some other iteration.

Example:

[ “first_prj”, “second_prj” ].each {
project_name->GitLabJsonApiBranchesFor(project_name).each {
branch->job (“${project_name}-${branch}”) {
scm {
git “git@om-git.mm.local:${project_name}”
}
steps {
shell ‘scripts/build.sh’
}
}
}
}
  1. Extend the DSL language using a library of helpers that can be reused in multiple jobs.

Example:

// Filename: common.groovyclass common {
static {
ScmContext.metaClass {
myGit { String url, Closure configure = null ->
git {
delegate.remote {
delegate.url(url)
delegate.credentials('jenkins')
}
delegate.branch 'develop'
delegate.configure(configure)
}
}
}
}
}
// Filename: real_job.groovyimport common # common.groovy must be in the same folder
use(common) {
job(‘example’) {
scm {
// use the custom ScmContex agtGit helper
myGit(‘git@om-git.mm.local:someproject.git’)
}
}
}
  1. The Jenkins Job DSL supports most of the plugins available to Jenkins, but from time to time Job DSL needs to generate XML lines for config.xml that are not supported out of the box. For this purpose, most DSL helpers (and the main project helper) have a configure block that can generate XML directly.

Example:

job(‘example_sonar_job’) {
steps {
sbt()
}
// force order (sonar runs second) in config.xml
configure {
it / ‘builders’ / ‘hudson.plugins.sonar.SonarRunnerBuilder’
}
}

Prodops.io is a boutique agency providing consulting, training, and IT services to startups, SMBs, and enterprises.

--

--