Creating a Jenkins Job with Pipeline: A Step-by-Step Guide

Hello Everyone,

Today lets see how to create a Jenkins pipeline and send notifications via slack and mails and create a docker image and run.

Introduction:

In the world of DevOps, Jenkins is a popular automation server that allows you to build, test, and deploy your applications efficiently. In this blog post, we will walk you through the process of creating a Jenkins job using a pipeline script. We'll explain each step in detail and provide insights into how the pipeline works.

prerequisites:

  • Jenkins (open JDK 11)
  • Jenkin plugins 
  1. Maven Integration plugin
  2. Pipeline Maven Integration Plugin
  3. GitHub plugin
  4. Email Extension Plugin
  5. Slack Notification Plugin
Now lets follow the steps to create a pipeline:-

Step 1: Set up the Pipeline Script

To begin, open your Jenkins instance and create a new job. Select the "Pipeline" type and enter a suitable name. In the job configuration, locate the "Pipeline" section and select the "Pipeline script" option. This is where you will define your pipeline script.



Step 2: Agent and Tools Configuration

The first section of the pipeline script is the agent block, which specifies where the job will run. In our case, we use agent any to allow the job to run on any available Jenkins agent.

Next, we define the tools required for the job using the tools block. In our example, we specify that we need the Maven tool with the identifier 'maven' to be installed and available for the job.



Step 3: Define Stages

A Jenkins pipeline consists of stages, which represent logical divisions of your job. Each stage contains one or more steps that define the actions to be executed. In our example, we have four stages: Checkout, Build, Copy JAR, Build Docker Image, and Run Docker Container.


3.1 Stage: Checkout

This stage is responsible for checking out the source code from the Git repository. We specify the branch, credentials for accessing the repository, and the URL of the repository.



3.2 Stage: Build

In this stage, we navigate to the project's directory and execute a Maven command to build the project. The command mvn clean package is used to clean the project, compile the source code, and package it into a JAR file. We also skip the tests and checkstyle during the build process.


3.3 Stage: Copy JAR

Once the build is successful, this stage copies the generated JAR file from the workspace to the desired destination, which is /dg-ds/test/ in our case.



3.4 Stage: Build Docker Image

Here, we navigate to the destination directory and build a Docker image using the provided Dockerfile. The command docker build -t test:v1 -f /dg-ds/test/Dockerfile . builds an image with the tag 'test:v1' from the Dockerfile.


5 Stage: Run Docker Container

In the final stage, we run a Docker container using the built image. The command docker run -d -p 8081:8081 --name test test:v1 starts a container with the name 'test' and maps port 8081 on the host to port 8081 inside the container.



Step 4: Post-Build Actions

After the pipeline execution, we have a post block that defines actions to be performed regardless of the build result. In our case, we send an email notification and a Slack message.

4.1 Sending Email Notification

We construct an email subject and body, including build details such as status, duration, triggered by, etc. If the build fails, we append the error message and the last 5 commit details to the email body. Finally, we use the emailext plugin to send the email.

4.2 Sending Slack Message

Based on the build result, we generate a Slack message with relevant information about the job. The message is sent to a specified channel using the slackSend step, along with the appropriate color for visual differentiation. 

Complete Script : -


pipeline {

  agent any

  

  tools {

    maven 'maven'

  }

  

  stages {

    stage('Checkout') {

      steps {

        git branch: 'sprint03',

            credentialsId: 'em-github',

            url: 'https://github.com/em-tirupati/em-dg-backup.git'

      }

    }

    

    stage('Build') {

      steps {

        dir('/var/lib/jenkins/workspace/Test-demo/em-dg-backup/') { 

          sh 'mvn clean package -DskipTests -Dcheckstyle.skip=true'

        }

      }

    }

    

    stage('Copy JAR') {

      steps {

        

        sh 'cp /var/lib/jenkins/workspace/Test-demo/em-dg-backup/target/*.jar /dg-ds/test/'

      }

    }

    

    stage('Build Docker Image') {

      steps {

        sh 'cd /dg-ds/test/'  

        sh 'docker build -t test:v1 -f /dg-ds/test/Dockerfile .'

      }

    }

    

    stage('Run Docker Container') {

      steps {

        sh 'docker run -d -p 8081:8081 --name test test:v1'

      }

    }

  }

  

  post {

    always {

      script {

        def triggerTime = new Date(currentBuild.startTimeInMillis)

        def completionTime = new Date()

        def duration = currentBuild.durationString

        def user = currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause)?.userId ?: 'unknown'

        def buildNumber = env.BUILD_NUMBER.toInteger()

        

        // Determine the time period for the email subject

        def timePeriod = ""

        if (triggerTime.hours >= 8 && triggerTime.hours < 11) {

          timePeriod = "Breakfast Build"

        } else if (triggerTime.hours >= 11 && triggerTime.hours < 13) {

          timePeriod = "Snack Build"

        } else if (triggerTime.hours >= 13 && triggerTime.hours < 16) {

          timePeriod = "Lunch Build"

        } else if (triggerTime.hours >= 16 && triggerTime.hours < 19) {

          timePeriod = "Tea Build"

        } else if (triggerTime.hours >= 19 && triggerTime.hours < 23) {

          timePeriod = "Dinner Build"

        } else {

          timePeriod = "Nightly Build"

        }

        

        def buildStatus = currentBuild.result.toLowerCase()

        def emailSubject = "DgDs Jenkins: ${timePeriod} (${currentBuild.fullDisplayName}): ${buildStatus.capitalize()}"

        def emailBody = """

Hi,


The Jenkins Job "${currentBuild.fullDisplayName}" has completed.


BUILD STATUS: ${currentBuild.result.toUpperCase()}


Build URL: ${env.BUILD_URL}

Build Trigger Time: ${triggerTime}

Build Completion Time: ${completionTime}

Build Duration: ${duration}

Build Triggered By: ${user}


Regards,

EM Tirupati - DgDs DevOps


-------------------------------------------------------------------------------

"""

        

        if (currentBuild.result == 'FAILURE') {

          def lastCommits = sh(returnStdout: true, script: 'git log -n 5 --pretty=format:"%h - %an, %ar : %s"').trim()

          def errorMessage = currentBuild.rawBuild.getLog(100).join('\n')

          

          emailBody += """

Error Message: 


${errorMessage}

          

Last 5 Commits:


${lastCommits}


Regards,

EM Tirupati - DgDs DevOps  

---------

"""

          

          emailext (

            subject: emailSubject,

            body: emailBody,

            to: "bhanureddybandi@gmail.com",

            mimeType: 'text/plain',

            replyTo: '',

            from: 'em.tirupati.dgds.devops@gmail.com'

          )

        

        } else {

          emailext (

            subject: emailSubject,

            body: emailBody,

            to: "bhanureddybandi@gmail.com",

            mimeType: 'text/plain',

            replyTo: '',

            from: 'em.tirupati.dgds.devops@gmail.com'

          )

        }

        

        // Slack message for success, failure, and aborted

        def slackMessage = ""

        def slackColor = ""

        if (currentBuild.result == 'SUCCESS') {

          slackMessage = "Build SUCCESS: Job Name: ${env.JOB_NAME}   Build Number: ${env.BUILD_NUMBER} Click To Know (<${env.BUILD_URL}|Open>)"

          slackColor = "#00FF00"

        } else if (currentBuild.result == 'FAILURE') {

          slackMessage = "Build FAILURE: Job Name: ${env.JOB_NAME}   Build Number: ${env.BUILD_NUMBER} Click To Know (<${env.BUILD_URL}|Open>)"

          slackColor = "#FF0000"

        } else if (currentBuild.result == 'ABORTED') {

          slackMessage = "Build ABORTED: Job Name: ${env.JOB_NAME}   Build Number: ${env.BUILD_NUMBER} Click To Know (<${env.BUILD_URL}|Open>)"

          slackColor = "#FFFF00"

        }

        

        slackSend channel: 'tpt-jenkins-test',

                  color: slackColor,

                  message: slackMessage,

                  tokenCredentialId: 'jenkins-slack'

      }

    }

  }

}

Conclusion:

In this blog post, we explored the process of creating a Jenkins job using a pipeline script. We learned about the different stages involved, including checkout, build, copying JAR files, building a Docker image, and running a Docker container. Additionally, we covered the post-build actions of sending email notifications and Slack messages. Jenkins pipelines offer a flexible and scalable approach to automate your software delivery process, making it an essential tool for any DevOps team.

By utilizing the pipeline script provided in this blog post, you can easily set up a job that fetches source code from a Git repository, builds the project using Maven, copies the generated JAR file to a specific location, builds a Docker image, and runs it as a container. The email notifications and Slack messages ensure effective communication and provide insights into the build status, duration, and other relevant information.

It's important to note that Jenkins pipelines can be customized according to your specific project requirements. You can add additional stages, steps, or integrations as needed to optimize your CI/CD workflows. Jenkins offers a rich ecosystem of plugins and integrations, allowing you to extend its functionality and integrate with other tools in your software development lifecycle.

With Jenkins and pipelines, you can achieve continuous integration and delivery, automate repetitive tasks, improve collaboration among team members, and ensure consistent and reliable software deployments. Whether you are working on a small-scale project or a large enterprise application, Jenkins can significantly enhance your development and deployment processes.

Start exploring Jenkins pipelines and experience the power of automation in your software development journey. Happy Jenkins automation!


Thank you

Bhanu Prakash Reddy
DevOps Protectors,
Data Shield  & Data Guard Team,
Enterprise Minds.

Comments

Popular posts from this blog

Encryption & Decryption for PostgreSQL (Command-Line)

Understanding Docker as a Toddler