Table of contents

Creating pipelines


Setting up a basic build pipeline

Creating a pipeline in Jenkins with Pipeline is as simple as a basic script:

node(‘linux’){
  git url: 'https://github.com/jglick/simple-maven-project-with-tests.git'
  def mvnHome = tool 'M3'
  env.PATH = "${mvnHome}/bin:${env.PATH}"
  sh 'mvn -B clean verify'
}

Where node is the step that schedules the tasks in the following block on whatever node with the label specified in its argument. In this case, the block’s tasks will only be run on a node with the label ‘linux’. The node block is required to tell Jenkins what system to run the commands.

git is the step that specifies what source code repository code should be checked from and does the checkout at this point.

The tool step makes sure a tool with the given name, in this case, a specific version of the Maven build tool, is installed on the current node. Merely running this step does not do much good; the script needs to know where it was installed, so the tool can be run later. For this, we need a variable.

The def keyword in Groovy is the quickest way to define a new variable, hence the "def mvnHome". The return value of the tool ‘M3’ check is assigned to the mvnHome variable.

Pipeline also allows for the creation of very complex pipelines, with parallel stages, conditional logic gates, and for definitions to be loaded from version control and shared between Pipelines. This allows for pipelines and certain standardized scripts to be shared between teams and changes to these scripts to be protected and reviewed by an administrator.

Here is an example script for such a scenario, where the bulk of the script is version controlled in GitHub:

def flow
node('master') {
    git branch: 'master', changelog: false, poll: true, url: 'https://github.com/lavaliere/workflow-plugin-pipeline-demo.git'
    flow = load 'flow.groovy'
    flow.devQAStaging()
}
flow.production()

And here is the example script’s GitHub counterpart:

def devQAStaging() {
    env.PATH="${tool 'Maven 3.x'}/bin:${env.PATH}"
    stage 'Dev'
    sh 'mvn clean install package'
    archive 'target/x.war'
  try {
        checkpoint('Archived war')
    } catch (NoSuchMethodError _) {
        echo 'Checkpoint feature available in Jenkins Enterprise by CloudBees.'
    }
    stage 'QA'
    parallel(longerTests: {
        runWithServer {url ->
            sh "mvn -f sometests/pom.xml test -Durl=${url} -Dduration=30"
        }
    }, quickerTests: {
        runWithServer {url ->
            sh "mvn -f sometests/pom.xml test -Durl=${url} -Dduration=20"
        }
    })
    stage name: 'Staging', concurrency: 1
    deploy 'target/x.war', 'staging'
}
def production() {
    input message: "Does http://localhost:8888/staging/ look good?"
    try {
        checkpoint('Before production')
    } catch (NoSuchMethodError _) {
        echo 'Checkpoint feature available in Jenkins Enterprise by CloudBees.'
    }
    stage name: 'Production', concurrency: 1
    node {
        unarchive mapping: ['target/x.war' : 'x.war']
        deploy 'target/x.war', 'production'
        echo 'Deployed to http://localhost:8888/production/'
    }
}
def deploy(war, id) {
    sh "cp ${war} /tmp/webapps/${id}.war"
}
def undeploy(id) {
    sh "rm /tmp/webapps/${id}.war"
}
return this;

More information on complex Pipelines can be found in Automating a project with a Jenkinsfile and in the Pipeline repository.