Technotes for future me

Jenkins pipeline DSL

Tutorial Using the Jenkins Job DSL

Using Kubernetes

When running jobs as Kubernetes pods you need to specify/inherit podTemplates

def label = "mypod-${UUID.randomUUID().toString()}"    // ugly necessary workaround
podTemplate(label: label, containers: [
  // You can have as many containers as you want...
  containerTemplate(name: 'maven', image: 'maven:3.3.9-jdk-8-alpine', ttyEnabled: true, command: 'cat'),
  containerTemplate(name: 'golang', image: 'golang:1.8.0', ttyEnabled: true, command: 'cat')
]) {

  node(label) {
    container('maven') {
      // do something with Maven
    container('golang') {
      // do something with go

Instead of explicitely specifying the pod template you can inherit templates and overwrite only some of the values…

podTemplate(label: 'mypod', inheritFrom: 'basepod) {

Understand the internals

Keep in mind the following:

  • there is always a container ‘jnlp’ which runs the Jenkins agent
  • when you do not use container('...') {} you are running inside the ‘jnlp’ container
  • you can override the ‘jnlp’ container by defining your own containerTemplate(name:'jnlp', ...)
  • SCM checkout always happens in the ‘jnlp’ container!


If you want to build docker images you have to run docker on-top of kubernetes. One possibility is Docker-in-Docker (DinD). Example:

podTemplate(label: 'dind', containers: [
  containerTemplate(name: 'docker', image: 'docker:dind', ttyEnabled: true, privileged: true,
    command: 'dockerd --host=unix:///var/run/docker.sock --host=tcp:// --storage-driver=overlay')
  volumes: [emptyDirVolume(memory: false, mountPath: '/var/lib/docker')]) {
    container(docker) {

Different DSL Syntax types

  • Declarative Pipeline (always has a ‘stages’ block, no loops/arithmetics/string processing)
  • Scripted Pipeline (always has a ’node’ block, full Groovy features)
  • Mixed Pipelines (using a ‘script’ block, do full Groovy inside a declarative pipeline)
  • JobDSL (always has something like a ‘pipelineJob’, otherwise full Groovy features)

Accessing the workspace

Check if a file exists

if (fileExists('file')) {
   // ...

Getting shell output

Either via reading from file

sh "echo something >output.txt";
def output =readFile('output.txt').trim()

or using the sh plugin

def output = sh(returnStdout: true, script: 'echo something').trim()

Handling the environment

Setting env variables

pipeline {
  environment {
     FOO = "BAR"

Query all env variables

node {
  echo sh(returnStdout: true, script: 'env | sort')

Access an env variable

echo env.BUILD_ID
echo "My build is is ${env.BUILD_ID}"

SCM Checkout

For Jenkinsfiles located in the repo perform checkout like this

checkout scm

For advanced checkout specifics of the SCM provider can be overwritten like this

checkout([$class: 'GitSCM', 
    branches: [[name: '*/master']], 
    doGenerateSubmoduleConfigurations: false, 
    extensions: [], 
    submoduleCfg: [], 
    userRemoteConfigs: [[]]

For example git LFS support can be enabled like this

checkout([$class: 'GitSCM', 
    extensions = [
      [$class: 'GitLFSPull'],
      [$class: 'CloneOption',
      depth: 0,
      noTags: false,
      shallow: true,
      timeout: 10]

To get checkout details catch the result of ‘checkout’

 def scmVars = checkout scm
 println scmVars.GIT_BRANCH
 println scmVars.GIT_COMMIT
 println scmVars.GIT_URL

Alternatetivly checkout repos directly using the git plugin anywhere in your pipeline as needed

git credentialsId: 'github', url: ${REPO_URL}, branch: 'master'


Username and Password

Fetch user and password into env variables

                   credentialsId: 'myCredentials',
                   usernameVariable: 'USER',
                   passwordVariable: 'PASSWORD'
               )]) {
  sh 'echo user "$USER" pasword "$PASSWORD"'


withCredentials([[$class: 'UsernamePasswordMultiBinding',
                  credentialsId: 'myCredentials', 
                  usernameVariable: 'USER', 
                  passwordVariable: 'PASSWORD'
                ]]) {
  sh 'echo user "$USER" pasword "$PASSWORD"'

Secret Files

withCredentials([file(credentialsId: 'myCredentials', variable: 'MY_SECRET_TOKEN')]) {
   sh 'echo token "$MY_SECRET_TOKEN"'

Docker Registry Credentials

Do this using the docker plugin, not via the credential-binding plugin!

docker.withRegistry('', 'myCredential') {

Jenkins Shared Libraries

Script Security

  • Use global shared libraries to by-pass script security
  • Use per-folder libraries for enforced script security

Including Shared Libraries

From repo

   identifier: 'jenkins-shared-library@1.0',
   retriever: modernSCM([
     $class: 'GitSCMSource',
     remote: ''

From local Jenkins

For this to work you have to configure a global or per-folder shared library which you can then include by name

 @Library('my-shared-library') _
 @Library('my-shared-library@1.0') _
 @Library(['my-shared-library', 'otherlib@abc1234']) _

Note the underscore for importing in contrast to importing classes

 import com.mycorp.pipeline.somelib.Helper
Last updated on 31 Jan 2021
Published on 24 Dec 2019
Edit on GitHub