Creating a Jenkins pipeline is not fastly different from creating a freestyle project. Select the "Pipeline" option in the job creation screen to get started. We’ll use the job name todo-spring-boot
for now to reflect the project name on GitHub.
For pipeline definitions we have two options:
-
Defining a pipeline script in the Jenkins job that can be edited on-the-fly.
-
Referring to a pipeline script from SCM.
In the light of Infrastructure as code, we’ll go with option 2. The Github repository already contains the file defining the desired layout and configuration of the pipeline for our job. By default, this file is called Jenkinsfile
. Listing 1 shows pipeline definition in its full beauty.
pipeline {
agent any
triggers {
pollSCM('*/5 * * * *')
}
stages {
stage('Compile') {
steps {
gradlew('clean', 'classes')
}
}
stage('Unit Tests') {
steps {
gradlew('test')
}
post {
always {
junit '**/build/test-results/test/TEST-*.xml'
}
}
}
stage('Long-running Verification') {
environment {
SONAR_LOGIN = credentials('SONARCLOUD_TOKEN')
}
parallel {
stage('Integration Tests') {
steps {
gradlew('integrationTest')
}
post {
always {
junit '**/build/test-results/integrationTest/TEST-*.xml'
}
}
}
stage('Code Analysis') {
steps {
gradlew('sonarqube')
}
}
}
}
stage('Assemble') {
steps {
gradlew('assemble')
stash includes: '**/build/libs/*.war', name: 'app'
}
}
stage('Promotion') {
steps {
timeout(time: 1, unit:'DAYS') {
input 'Deploy to Production?'
}
}
}
stage('Deploy to Production') {
environment {
HEROKU_API_KEY = credentials('HEROKU_API_KEY')
}
steps {
unstash 'app'
gradlew('deployHeroku')
}
}
}
post {
failure {
mail to: 'benjamin.muschko@gmail.com', subject: 'Build failed', body: 'Please fix!'
}
}
}
def gradlew(String... args) {
sh "./gradlew ${args.join(' ')} -s"
}
Listing 1. The pipeline definition as code
As you can see in the listing, the code is very readable and understandable even if you do not know the syntax in more detail. The script defines each stage of the pipeline in order. Each stage may contain one or many steps. The actual "work" of the pipeline happens under the covers and is performed by Gradle. Jenkins merely acts as orchistration engine.
Let’s see what happens when we execute the job by triggering the "Build Now" action. Jenkins runs through all stages of the pipeline up until the point that requires manual execution. In the console view, you can confirm or abort the manual execution to trigger the deployment to production. Below you can find the standard view of the pipeline in the job.
Figure 4. Jenkins stage view
You might have noticed that the standard job view of the pipeline does not render parallel stages or manual triggers. Blue Ocean makes a much better attempt at rendering those features. In the next section, we’ll have a brief look at what Blue Ocean pipeline views have to offer.