In the previous two articles A Simple Freestyle Job in Jenkins and Build a Docker Image with a Jenkins Freestyle Job in this Jenkins series, we created freestyle jobs. Now it’s time to look into Pipeline jobs.
What is a Pipeline in Jenkins?
A pipeline is a sequence of steps that needs to be followed in order to a deliver a new version of software. It includes steps from checking in the latest code into SCM to delivering and deploying the final application to production system.
A Jenkins Pipeline is a set of plugins that supports implementing and integrating continuous delivery pipelines.
Jenkinsfile
All the stages and steps that define the pipeline are written in a file called the Jenkinsfile
. This file is usually committed to the source code repository of the project so that it can be maintained and versioned along with the project.
Some benefits of keeping the Jenkins file in SCM could be listed as follows.
- Creates a build pipeline for all the branches of the project automatically.
- Reviewing the build pipeline code and making necessary changes is easier as it is maintained with the project.
- Single source of truth for the pipeline as anyone involved in the project has access to the
Jenkinsfile
.
Jenkinsfile
can be written in two syntax types.
- Declarative – richer syntactical features, hence easier to write.
- Scripted – advanced and complex compared to declarative syntax.
In this article, we will be focusing on the declarative syntax.
Declarative Pipeline Syntax
Skeleton of a Jenkinsfile
written with declarative pipeline syntax would look like below.
pipeline{
agent any
stages{
stage('Build'){
steps{
echo "Building..."
}
}
stage('Test'){
steps{
echo "Testing..."
}
}
stage('Deploy'){
steps{
echo "Deploying..."
}
}
}
}
Let me explain each block in above skeleton code.
pipeline
– everything that happens throughout the pipeline is defined inside thepipeline
block.agent
– specifies where to execute the pipeline. Instructs Jenkins to allocate an executor and a workspace for the pipeline. Mostly relevant when you have a Jenkins cluster with master and slave nodes.stages
– a distinct collection of tasks that happen during the pipeline are defined in a particularstage
in the pipeline. There are many stages in a pipeline such as build stage, test stage and deployment stage.steps
– tasks within astage
, such as executing shell commands.
Now let’s look at how to convert the freestyle job we configured in the previous article into a pipeline job.
Jenkinsfile for Our Application
Now this is the same Spring Boot project we used in the previous articles. We are going to build the project with maven in the first stage. Then we will build the Docker image and push it to Docker Hub. You can find the GitHub repository for this project here.
Jenkinsfile
for this pipeline would look like below.
pipeline{
agent any
tools{
maven "maven-3.8"
}
stages{
stage('Build and package war file') {
steps{
script{
echo "Packaging war file..."
sh "mvn clean package -Dmaven.test.skip=true"
}
}
}
stage('Build Docker image'){
steps{
script{
echo "Building Docker image..."
withCredentials([usernamePassword(credentialsId: "dockerhub-credentials", usernameVariable: "username", passwordVariable: "password")]){
sh "docker build -t dcharith/mobile-app-ws:2.0 ."
sh "echo $password | docker login -u $username --password-stdin"
sh "docker push dcharith/mobile-app-ws:2.0"
}
}
}
}
stage('test'){
steps{
echo 'This is the test step!'
}
}
stage('deploy'){
steps{
echo 'This is the deploy step!'
}
}
}
}
Important parts of this Jenkinsfile
- Line 3 –
tools
section specifiesmaven-3.8
. This is because we are using Maven 3.8 to build this project. Note that you must have maven-3.8 already added as a build tool from Jenkins UI and you should give the correct ID here. You can find more details here. - Line 7 – denotes the start of the first stage of our pipeline. In this stage, we are building the project using Maven. Notice that the
mvn -Dmaven.test.skip=true clean package
command is inside another block calledscript
, which inside thesteps
block.sh
here is a step in the pipeline that will execute the shell command given inside the quotes. - Line 15 – denotes the start of the second stage. In this stage, we are building the Docker image.
- Line 19 – all our
docker
commands go inside thiswithCredentials
block.credentialsId
here refers to the ID we gave for Docker Hub credentials in Jenkins credentials configuration. Make sure to look this up from Jenkins UI and give the correct value here. You can read more about how to add credentials here. To find the credentials ID, from Jenkins home page, navigate to Manage Jenkins -> Manage Credentials and copy the correct ID as shown in below picture.usernameVariable
andpasswordVariable
are used to pass username and password as variables when logging into docker in line 21.
I hope the other lines are self explanatory. (If not, feel free to drop a comment 🙂 )
Once the file is written, we can check it into the source code repository of our project. This file should usually be in the root directory of the project.
Configure the Pipeline Job
To configure the pipeline, in Jenkins dashboard, click on “New Item”.
Give an appropriate name and create a Pipeline job.
Scroll down to the Pipeline section and fill in the details as below.
- Select “Pipeline script from SCM” from the drop down. What this will do is fetch the
Jenkinsfile
from the source code repository. Therefore it should be in our GitHub repository as I mentioned previously. - Select Git as the SCM.
- Give the correct URL to the Git repository.
- Select correct credentials for the repository.
Scroll further down and fill in following details as well.
- Specify the branch you want to build in “Branch Specifier” field. To build multiple branches, there is another pipeline type called multi-branch pipelines, which we will discuss in the next article.
- Repository browser can be “Auto”.
- Script path should be
Jenkinsfile
. It is the convention to name theJenkinsfile
as such, so better to follow it as a good practice.
Once done, click save and we are ready to build!
Run the Pipeline in Jenkins
To run the pipeline, simply click on “Build Now” as highlighted.
You can see that the build is in progress from the Build History section. In above example, it has finished checking out code from SCM and installing build tools successfully and in the progress of packaging the war file using Maven as shown in stage view.
Once all stages are completed, you can see the completed pipeline build as below.
We can see the console output of our pipeline by clicking on the date under build history highlighted above.