Structure of a Scripted Pipeline in Jenkins with sample code

There are two ways of writing pipeline code in jenkins, scripted and declarative. Here we will discuss how to start with writing a scripted pipeline in Jenkins. We will write pipeline code for a java web app project using maven, however high level structure will hold true for any project type.
First let us discuss the high level structure. The pipeline code is structured here as a try catch block for error handling though it is not mandatory to enclose the script within try catch block.
node {
try{
stage('') {
}
...
}
catch(err)
{
currentBuild.result ="FAILURE"
step([$class: 'Mailer', notifyUnstableEveryBuild:true, recipients:'', sendToIndividuals: true])
throw err
}
}
node
node
is a scripted pipeline-specific syntax that instructs Jenkins to execute this pipeline on any available agent if not specified. If you want the pipeline code or the code for any particular stage to be run on a specific agent, you can provide the agent in a bracket against the node keyword or the stage keyword resp.
node(label:'master') {
stages
Git Checkout Stage
The first step is usually to download the latest code into the Jenkins workspace. This step is not mandatory and you can also work from your project folder in a different location than Jenkins workspace, however this is the most common scenario.
For checking out the code, we will simply use the following code for the stage Git Checkout.
stage("Git Checkout"){
git credentialsId: 'githubcredentials', url: 'https://github.com/githubusername /githubreponame'
echo 'Git Checkout Completed'
}
Make sure to replace githubusername with your GitHub username and githubreponame with the name of your repository in GitHub.
Compile and Unit Test Stage
Our next stage is a Compile and Unit Test stage. Maven should be configured in Jenkins to run the code mentioned below
stage('Compile and Unit Test') {
bat 'mvn clean test'
echo 'Compile and Unit Test Completed'
}
The above code will run on windows. To run on linux, all you need is to replace the bat command with sh command as follows
sh ‘mvn clean test’
This stage uses two maven goals clean and test. This will first clean all the files and directories generated inside target directory during previous builds.
Maven has a lifecycle. If you call a specific phase, all previous phases are also called automatically. So if you call mvn test, it will compile your classes and your test classes and run the tests.
We could have also mentioned compile and test goals separately if required as follows and run them as a batch or shell script in two separate stages
mvn clean compile
mvn test
If the path to pom.xml is not provided explicitly, Jenkins will search for pom.xml in the workspace created by Jenkins for the job by default.
In this case, we need to specifically mention the path for pom.xml.The switch – f is used to provide the path of pom.xml. This is shown in the code snippet below. The variable used for storing the path is defined outside of this stage and hence can be accessed by all stages in this pipeline.
def pomfilepath= < ... >
stage('Compile and Unit Test') {
bat 'mvn -f '+ pomfilepath +' clean test'
echo 'Compile and Unit Test Completed'
}
Do not forget to replace bat command with sh for linux.
Lastly, the following echo command will print this statement in the logs.
echo 'Compile and Unit Test Completed'
SonarQube Analysis and Quality Gate
Let us see the pipeline stages for SonarQube Analysis and Quality Gate for a java and maven project. Replace bat with sh on linux OS
stage('Static Analysis')
{
withSonarQubeEnv('SonarQube1')
{
bat 'mvn sonar:sonar
echo 'Static Analysis Completed'
}
stage("Quality Gate"){
timeout(time: 1, unit: 'HOURS')
{
waitForQualityGate abortPipeline: true
def qg= waitForQualityGate()
if (qg.status!= 'OK'){
error "Pipeline aborted due to quality gate failure: ${qg.status}"
}
}
echo 'Quality Gate Passed'
}
To understand all the steps required to integrate SonarQube with Jenkins, refer the post SonarQube integration with Jenkins
Package and Deploy stages
Next we will add stages Package and Deploy to the pipeline as shown below.
stage('Package') {
bat 'mvn -U -DskipTests package'
echo 'Package Completed'
}
stage('Deploy') {
bat 'mvn -U -DskipTests tomcat7:deploy -Dtomcat.username=<tomcatserverusername> -Dtomcat.password =<tomcatserverpassword>'
echo 'Deploy Completed'
}
Maven goal for package and deploy will execute all previous goals in the maven life cycle which also includes unit tests. As we have already passed the unit tests in the previous stage of this pipeline, we can skip them by using – U switch.
In the deploy stage, we deploy the code to tomcat server. You need to provide the username a password for your tomcat server.
try catch block
The code in the catch block will mark the pipeline result as failed in case of an error. It will then send the failure notification with log details to the specified recipient email id. It will be able to send email only if the sender email address is pre-configured in Jenkins. As a last step, it will throw the error. You can refer to the code for the catch block and the complete pipeline from the below pipeline script.
For the sake of simplicity we will first mention the code assuming pom.xml is in the Jenkins project workspace and then provide the same code assuming that we need to provide path to pom.xml explicitly.
Pipeline code
node(label:'master') {
try{
stage('Compile and Unit Testing') {
bat 'mvn clean test'
echo 'Compile and Unit Test Completed'
}
stage('Static Analysis')
{
withSonarQubeEnv('SonarQube1')
{
bat 'mvn sonar:sonar
echo 'Static Analysis Completed'
}
stage("Quality Gate"){
timeout(time: 1, unit: 'HOURS')
{
waitForQualityGate abortPipeline: true
def qg= waitForQualityGate()
if (qg.status!= 'OK'){
error "Pipeline aborted due to quality gate failure: ${qg.status}"
}
}
echo 'Quality Gate Passed'
}
stage('Package') {
bat 'mvn -U -DskipTests package'
echo 'Package Completed'
}
stage('Deploy') {
bat 'mvn -U -DskipTests tomcat7:deploy -Dtomcat.username= -Dtomcat.password='
echo 'Deploy Completed'
}
}
catch(err){
currentBuild.result = "FAILURE"
step([$class: 'Mailer', notifyUnstableEveryBuild:
true,recipients:'', sendToIndividuals: true])
throw err
}
}
Pipeline code with path for pom.xml
node(label:'master') {
try{
def pomfilepath='< ... >'
stage('Compile and Unit Testing') {
bat 'mvn -f '+ pomfilepath +' clean test'
echo 'Compile and Unit Test Completed'
}
stage('Static Analysis')
{
withSonarQubeEnv('SonarQube1')
{
bat 'mvn -f '+ pomfilepath +' sonar:sonar
echo 'Static Analysis Completed'
}
stage("Quality Gate"){
timeout(time: 1, unit: 'HOURS')
{
waitForQualityGate abortPipeline: true
def qg= waitForQualityGate()
if (qg.status!= 'OK'){
error "Pipeline aborted due to quality gate failure: ${qg.status}"
}
}
echo 'Quality Gate Passed'
}
stage('Package') {
bat 'mvn -U -DskipTests -f'+ pomfilepath +' package'
echo 'Package Completed'
}
stage('Deploy') {
bat 'mvn -U -DskipTests -f '+ pomfilepath +' tomcat7:deploy -Dtomcat.username= -Dtomcat.password='
echo 'Deploy Completed'
}
}
catch(err){
currentBuild.result = "FAILURE"
step([$class: 'Mailer', notifyUnstableEveryBuild:
true,recipients:'', sendToIndividuals: true])
throw err
}
}
Once you have created the pipeline, you will need to build the code using “Build Now” from project dashboard and then check the console output for the detailed logs.
Let us know if you found this post helpful.