RMIT University

COSC2767 · Systems Deployment and Operations

Week 5: Jenkins for CI and CD Lab Guide

Create Jenkins jobs and pipelines that automate application build, test, and deployment stages.

🎯 Objective

Week tutorial screenshot from page 1

In this lab, we will learn to set up the basic pipeline of CI/CD of Jenkins to integrate it with Git, Github, Maven and Tomcat on two separate EC2 instances.

Screenshot illustrating Github, Maven and Tomcat on two separate EC2 instances.

🧭 Jenkins CI/CD pipeline overview

In this week lab, we will setup this CI/CD pipeline as below:

Screenshot illustrating In this week lab, we will setup this CI/CD pipeline as below:

As you can see, we are dealing with two different EC2 instances (which are very common for microservices).

🧰 Set up the Jenkins server

Screenshot illustrating Instructions to setup for the the EC2 Instance 1 (Jenkins Server)

Here are the overall steps to setup a Jenkin server on the first EC2 instance 1 (Jenkin Server):

  • Setup a Linux EC2 Instance 1.

    • Install Java.

    • Install & Setup Maven.

    • Install & Setup Jenkins.

    • Integrate Jenkins with Github and Maven using plugins.

You task:

Let’s setup the EC2 instance for Jenkins Server like so:

  • Here are the settings of the Jenkin Server for EC2:

    • Name: Jenkins_Server

    • OS: default Amazon Linux 2023 AMI

Screenshot illustrating OS: default Amazon Linux 2023 AMI (1 of 2)Screenshot illustrating OS: default Amazon Linux 2023 AMI (2 of 2)
  • Instance Type: t3.micro

    • Key pair: select and reuse your old key in other labs (devops_project_key)

    • Storage: 15GB (since Jenkins build can be large for big projects)!

    • Security Group:

      • Optional Name: Jenkins_Security_Group

      • Source Type: Anywhere

      • Open two ports:

        • 22 for SSH

        • 8080 for Jenkins

  • After launching the instance then, in the EC2 dashboard you should see the Jenkin_Server EC2 running:

  • The most important information is the Public IP address of your EC2 instance which will allow us to connect SSH to the server to control it:

Screenshot illustrating us to connect SSH to the server to control it:
  • After that, let’s SSH to the Jenkins Server on EC2:

Screenshot illustrating After that, let’s SSH to the Jenkins Server on EC2:
  • To keep things simple without dealing with permission, let’s login as a root user and change our current directory to /root:

sudo su -
  • Now, you are now a root user with the highest permission privilege to install anything you want. You can check your current directory, which should tell you that you are at root directory:

Screenshot illustrating directory:

Allocate more disk space to Temp directory (/tmp) for Jenkins to work

  • Before installing Jenkins, let’s check the available disk space allocated for the Temporary directory (/tmp):

df -h /tmp
Screenshot illustrating df -h /tmp
  • So 475 MB is definitely not recommended by Jenkins, Jenkins might shutdown its agent node if the available disk space for /tmp goes below 1 GB and give warnings if it goes below 2 GB. Thus, let’s allocate 3 GB to our /tmp folder so Jenkins can work without any problem!

  • Open the /etc/fstab file which defines how and where disk partitions, devices, or other file systems should be mounted:

sudo nano /etc/fstab
  • At the end of the file, add the following line. This line tells the system to mount /tmp as a tmpfs with a size limit of 3GB every time the system boots:

    • tmpfs: Specifies the filesystem type, which is a temporary filesystem stored in RAM.

    • /tmp: The mount point. This means /tmp will be mounted as a tmpfs

    • defaults,size=3G: Mount options. defaults applies default settings, and size=3G limits the size to 3GB.

    • Dump: 0 means "do not dump" the filesystem for backups.

    • Fsck order: 0 means "do not check" the filesystem at boot.

tmpfs /tmp tmpfs defaults,size=3G 0 0
Screenshot illustrating tmpfs /tmp tmpfs defaults,size=3G 0 0
  • To apply the changes without rebooting the EC2, let’s manually remount /tmp:

mount -o remount /tmp
  • Check that /tmp is now mounted with the specified size:

Screenshot illustrating Check that /tmp is now mounted with the specified size:
  • [Optional] You can choose to reboot the EC2 server to double check if the /tmp directory’s space allocation would still have 3GB or revert back to 475MB:

Screenshot illustrating space allocation would still have 3GB or revert back to 475MB:

Install Jenkins

  • Cool, now we need to install Jenkins, let’s open this website: https://www.jenkins.io/download/

  • We should always use the “Stable (LTS)” version when it comes to development and deployment. Also, we will choose “RedHat/Fedora” since that is the Amazon Machine Linux (AMI) based on:

Screenshot illustrating (AMI) based on:
  • We should see the instructions to download and install Jenkins:

Screenshot illustrating We should see the instructions to download and install Jenkins:
  • So let’s follow those above instructions commands, copy them into the terminal:

    • First, these commands will import the repository of Jenkins to ensure our instance know where to download and install Jenkins from which repo:

sudo wget -O /etc/yum.repos.d/jenkins.repo \
  https://pkg.jenkins.io/rpm-stable/jenkins.repo
sudo yum upgrade
  • Second, Let’s install fontconfig and Java 21 which is requirement before we can install Jenkins:

    • Fontconfig’s purpose is to provide the necessary font management and configuration support to ensure that Jenkins can properly render fonts and display text when generating graphical content like charts, reports, or logs that include graphical elements.

sudo yum install fontconfig java-21-amazon-corretto
  • Finally, we can install jenkins after installing Java:

yum install jenkins
  • You should see the message like so:

Screenshot illustrating You should see the message like so:
  • Reloads systemd to recognize new or updated service files—like the Jenkins service just installed:

sudo systemctl daemon-reload

Start Jenkins

  • Now, we can check the current status of our jenkins:

service jenkins status
  • You should see that the status of jenkins is currently inactive (dead):

Screenshot illustrating You should see that the status of jenkins is currently inactive (dead):
  • You can start jenkins like so, it could take a few minutes to start:

service jenkins start

And you should see the message it is starting like so:

Screenshot illustrating And you should see the message it is starting like so:

Please be patient as it could take a few minutes for Jenkins to start for the first time.

  • Now, we can check the current status of jenkins again:

service jenkins status
  • You should see that the status of jenkins is currently running at the port number 8080:

Screenshot illustrating You should see that the status of jenkins is currently running at the port number 8080:
  • Now we can try to access Jenkins via the public IP address which I have mentioned before via the port number 8080 :

Screenshot illustrating the port number 8080 :
Screenshot illustrating the port number 8080 :
  • As you can see that, Jenkins tells you that the default admin password is in the file “/var/lib/jenkins/secrets/initialAdminPassword”, so we need to copy it and paste to the Adminstrator password to login to the Jenkin admin dashboard:

cat /var/lib/jenkins/secrets/initialAdminPassword
  • In my case, the default admin password is:

Screenshot illustrating In my case, the default admin password is:
  • Copy that string and paste that to the password login field and press Continue:

Screenshot illustrating Copy that string and paste that to the password login field and press Continue:

Initial Setup for Jenkins

  • Now, if the password is corrected, we are greeted with this page to install plugins. However, we are learning and want to install plugin one by one as we go, so let’s close (x) this page for now:

Screenshot illustrating for now:
  • That’s it! you can start to use Jenkins now! Remember, the username is “admin” and the password is the one you have accessed just now!

Screenshot illustrating password is the one you have accessed just now!
  • Now, you should see the Jenkins admin dashboard like below! Congrats, you have successfully installed Jenkins on an AWS EC2 instance and accessed its dashboard through a public IP address which is super cool!

Screenshot illustrating public IP address which is super cool!
  • Y ou can confirm that the /tmp disk space has been allocated to 3GB for Jenkins so all Jenkins agent nodes are working as usual without any problem.

Screenshot illustrating agent nodes are working as usual without any problem.
Screenshot illustrating agent nodes are working as usual without any problem.

[Optional - If you choose not to allocate more temp disk space as I instructed above] [STARTS] If you did not allocate more space for /tmp then the Jenkins agent node might be shutdown. Let’s fix a few things in the warning message before we can move on:

Screenshot illustrating few things in the warning message before we can move on:
  • Let’s select this option as we do not want Jenkins to force the agent node to be offline when the Temp Space (/tmp) is low on disk space so that we can build our Jenkins’ jobs without any problem.

Screenshot illustrating any problem.
  • Let’s bring our Jenkins agent node back online after we update the above setting:

Screenshot illustrating Let’s bring our Jenkins agent node back online after we update the above setting:

[Optional - If you choose not to allocate more temp disk space] [ENDS]

  • Setup the correct timezone of our location so it should be Asia/Ho Chi Minh so when we check out the build log in Jenkins, all of the date time of each build run is based on the correct timezone, which is very helpful to figure out the exact time when things goes wrong:

Screenshot illustrating correct timezone, which is very helpful to figure out the exact time when things goes wrong:
  • Setup a new password for the admin Jenkins user , so next time you login Jenkin dashboard, you can use the new password you set:

Screenshot illustrating you can use the new password you set:
  • After changing the password, you will get kicked out from the security page, please just refresh the URL of your jenkins dashboard and enter the admin username and your new password to login:

Screenshot illustrating password to login:

Run First Jenkins Job

We're gonna create a first Jenkins job for fun which only executes some simple bash command to demonstrate Jenkins.

  • If you are not in the main page of dashboard, click on the logo of Jenkins to be back to homepage:

Screenshot illustrating homepage:
  • Create a new item:

Screenshot illustrating Create a new item:
  • Enter the item name and select it to be Freestyle project:

Screenshot illustrating Enter the item name and select it to be Freestyle project:
  • Enter the description of this Jenkins job and select build to execute shell as we want to run the bash command line:

Screenshot illustrating the bash command line:
  • You can type the bash linux commands in the command shell like so:

Screenshot illustrating You can type the bash linux commands in the command shell like so:
  • Choose apply then save it to be sure your first Jenkins job is saved and redirect back to the dashboard of that job:

Screenshot illustrating dashboard of that job:
  • To execute the Jenkins job, we can click on the “Build Now” button!

Screenshot illustrating To execute the Jenkins job, we can click on the “Build Now” button!
  • Check the result of your Jenkins build:

Screenshot illustrating Check the result of your Jenkins build:
  • Now you should see the output of your build:

Screenshot illustrating Now you should see the output of your build:
  • This is exactly similar to how we have to run the bash command lines by typing them manually in the terminal! You can try to type the same bash commands to test it out:

Screenshot illustrating manually in the terminal! You can try to type the same bash commands to test it out:

Integrate Git & Github with Jenkins

Screenshot illustrating Integrate Git & Github with Jenkins

The overview steps:

  • Install Git on Jenkins EC2 instance

    • Install Github Plugin on Jenkins GUI

    • Configure Git on Jenkins GUI

  • Install git on the EC2 instance using this command:

yum install git

To confirm the installation, you need to type “y” for yes:

Screenshot illustrating To confirm the installation, you need to type “y” for yes:
  • After git installation, you can check the version of git:

git --version

You should see the current version of git installed like so:

Screenshot illustrating You should see the current version of git installed like so:
  • Let’s go back to the main dashboard page of Jenkins:

Screenshot illustrating Let’s go back to the main dashboard page of Jenkins:
  • It's time to install Git plugins on Jenkins GUI, go to manage plugins in Jenkins:

Screenshot illustrating It's time to install Git plugins on Jenkins GUI, go to manage plugins in Jenkins:
  • Search “ Github " plugins in the available plugins to install and select the first option:

Screenshot illustrating Search “ Github " plugins in the available plugins to install and select the first option:
  • You should wait for a few minutes for it to install all dependencies of the Github plugin before actually installed the Github plugin:

Screenshot illustrating before actually installed the Github plugin:
  • Let's configure the Github plugin we just installed:

Screenshot illustrating Let's configure the Github plugin we just installed:
  • As long as, the configuration looks like this, then it should be good enough:

Screenshot illustrating As long as, the configuration looks like this, then it should be good enough:
  1. Run Jenkins job to pull code from Github

In this session, we will use this github repo which only contains a very simple website like so

Screenshot illustrating In this session, we will use this github repo which only contains a very simple website like so
  • Please fork my repo on Github so it will copy the same repo to your Github so you can own the same copy of this repo on your own Github:

Screenshot illustrating the same copy of this repo on your own Github:
  • Note: Whenever I refer to this Github repo in this lab, then you should use your own forked Github repo to follow these instructions. Because you are required later on to commit and push changes to your own public forked Github repo in this tutorial.

  • You can copy the Repository URL of the this project on Github like so (use your own Github repo):

Screenshot illustrating repo):

The copied link of this hello world github repo is:

  • Create a new item in Jenkins:

Screenshot illustrating Create a new item in Jenkins:
  • Create a new job as following:

Screenshot illustrating Create a new job as following:
  • Fill in the details of this new job as following:

Screenshot illustrating Fill in the details of this new job as following:
  • Alright, it's time to build this job and see the result:

Screenshot illustrating Alright, it's time to build this job and see the result:
  • Let's check this result:

Screenshot illustrating Let's check this result:
  • You can double check if the jenkins job has pulled the simple website repo to the default workspace like it said. You should see that every files in the hello world repo are there in the jenkins workspace folder in EC2 instance:

Screenshot illustrating jenkins workspace folder in EC2 instance:
  • Or you can check out files and directories in the workplace of this job in the dashboard like so:

Screenshot illustrating so:

Yeah, so you know how to use Jenkin to create a job to pull code from a public Github repo. However, we need to use Maven to build this web project to create a WAR file.

Integrate Maven with Jenkins

Screenshot illustrating Integrate Maven with Jenkins
  • Important Note: Please install Maven on this Jenkin Server like you have practiced before in the previous lab. If you forgot then please open the previous lab to repeat the steps to install and set up Mavens (“Install Maven on the EC2 instance” section).

  • After you done everything correctly then you can call maven right from the bash like this:

    • Note the maven version could be different to yours in the screenshot.

mvn -v
Screenshot illustrating mvn -v

Now, we just need to let Jenkin know the locations of Maven folders.

  • Open Jenkins admin dashboard again, and go to manage plugins:

Screenshot illustrating Open Jenkins admin dashboard again, and go to manage plugins:
  • Let’s install Maven integration plugin:

Screenshot illustrating Let’s install Maven integration plugin:
  • You need to wait for it to install dependencies and the Maven integration plugin:

Screenshot illustrating You need to wait for it to install dependencies and the Maven integration plugin:
  • Let’s set up configuration settings for the Maven plugin. First, let’s tell Maven plugin where is the path of JDK:

Screenshot illustrating the path of JDK:
  • At the JDK section,

Screenshot illustrating At the JDK section,
  • Add JDK Name and JAVA_HOME as following:

    • Note that your JDK specific version number could be different to yours in the screenshot below:

Screenshot illustrating screenshot below:
  • Secondly, let’s tell Maven plugin where is the path of Maven in our EC2 instance:

Screenshot illustrating Secondly, let’s tell Maven plugin where is the path of Maven in our EC2 instance:
Screenshot illustrating Secondly, let’s tell Maven plugin where is the path of Maven in our EC2 instance:
  • The name is up to you so you can choose to name it as simple as “maven”.

Screenshot illustrating The name is up to you so you can choose to name it as simple as “maven”.
  • Time to apply and save the configuration for the JDK and Maven:

Screenshot illustrating Time to apply and save the configuration for the JDK and Maven:
  • Alright, it’s time to create a new Jenkins job to build our Maven project from github:

Screenshot illustrating Alright, it’s time to create a new Jenkins job to build our Maven project from github:
  • Select Maven project to be the Jenkins job type we want:

Screenshot illustrating Select Maven project to be the Jenkins job type we want:
  • Let’s fill in the details:

The description is up to you so name it meaningfully!

Screenshot illustrating The description is up to you so name it meaningfully!

The same details of Git and Github repo URL as before:

Screenshot illustrating The same details of Git and Github repo URL as before:
  • So let’s use “clean” and “package” for our Maven build phases:

    • As we have learnt, every Maven project has specific goals and options. In the previous lab, we use “mvn package” to compile and package the project into a WAR file. This time, we will use “mvn install” which will do all the things that “package” does, additionally it will add a packaged war file in the local repository as well. Also we are using the clean command, which will delete all previously compiled Java .class files and resources (like .properties) in your project. Your build will start from a clean slate every time!

Screenshot illustrating clean slate every time!

Time to apply and save:

Screenshot illustrating Time to apply and save:
  • Let’s get the real action of Jenkins:

Screenshot illustrating Let’s get the real action of Jenkins:

As you can see our jenkins job build successfully, by looking at the end of the log:

The webapp.war is built successfully (The WAR Plugin is responsible for collecting all artifact dependencies, classes and resources of the web application and packaging them into a web application archive )

Screenshot illustrating application archive )
Screenshot illustrating application archive )
  • You can check the location of the our first Maven project build as following:

Screenshot illustrating You can check the location of the our first Maven project build as following:
Screenshot illustrating You can check the location of the our first Maven project build as following:

So far, we got this CI (Continuous Integration) pipeline:

  • Our Jenkins pulls the code from Github to EC2 cloud instance.

    • Then Jenkins uses Maven to build the code to create WAR artifacts which are ready for deployment on the Tomcat web server!

🐈 Set up the Tomcat server

Screenshot illustrating Instructions to setup for the the EC2 Instance 2 (Tomcat Server)

[You can reuse your existing Maven_Tomcat_Server EC2 from last week tutorial to save time instead of setting up a new Tomcat EC2 server from beginning then skip to the “Instructions to setup Deployment on the Jenkins Server” section]

Here are the overall steps to setup a Jenkin server on the first EC2 instance 2 (Tomcat Server):

  • Setup a Linux EC2 Instance 2.

    • Install Java.

    • Install & Setup Tomcat.

    • Start Tomcat.

Screenshot illustrating Start Tomcat.
  • Access Tomcat Admin Web UI on port 8080.

You task:

Let’s setup the second EC2 instance for Tomcat Server like so:

  • Here are the settings of the Tom Server for EC2:

    • Name: Tomcat_Server

    • OS: default Amazon Linux 2023 AMI (Free-tier)

    • Instance Type: t2.micro (Free-tier)

    • Key pair: select and reuse your old key in other labs (devops_project_key)

    • Storage: Default 8 GB is plenty enough!

    • Security Group:

      • Optional Name: Tomcat_Security_Group

      • Source Type: Anywhere

      • Open two ports:

        • 22 for SSH

        • 8080 for Tomcat

        • 80 for HTTP (Optional but useful in the future)

        • 443 for HTTPS (Optional but useful in the future)

Screenshot illustrating 443 for HTTPS (Optional but useful in the future)
  • After launching it, you should have two EC2 instances like so:

Install and Setup for Java & Tomcat

  • Please SSH to the Tomcat Server.

Screenshot illustrating Please SSH to the Tomcat Server.
  • To keep things simple without dealing with permission, let’s login as a root user and change our current directory to /root:

sudo su -
  • The important dependency of Tomcat is JDK 21, so let’s install JDK21 with the usual installation command.

yum install java-21-amazon-corretto
  • Important Note: Please install Tomcat on this Tomcat Server like you have practiced before in the previous lab. If you forgot then please open the previous lab to repeat the steps to install and set up Tomcat (“Install Tomcat (Web Server) on the EC2 instance” section).

  • There are two important steps in the previous lab you need to do:

    • Please comment out or remove the local IP address restriction for the Tomcat manager in this file: /opt/tomcat/webapps/manager/META-INF/context.xml

    • Also, please do the steps to add a few users with right permissions to use Tomcat which is in the file tomcat-users.xml (/opt/tomcat/conf/tomcat-users.xml) as we will need to use the username and password of Tomcat later on:

Screenshot illustrating need to use the username and password of Tomcat later on:
  • Make you can see the Tomcat dashboard available via the public IP address of the EC2 instance via the port 8080:

Screenshot illustrating instance via the port 8080:

🚀 Configure deployment from Jenkins

  • After Tomcat installation in the second EC2 instance, Now, let’s go back to the first EC2 instance (Jenkins server) and install deployment plugin for Jenkins to deploy on Tomcat server:

Screenshot illustrating server:
  • Install the plugin “Deploy to Container”:

    • Its purpose is specifically for deploying Java web applications (e.g., .war files) to servlet containers like Tomcat.

Screenshot illustrating servlet containers like Tomcat.
Screenshot illustrating servlet containers like Tomcat.
  • Let’s add credentials of Tomcat users to deploy our web application:

Screenshot illustrating Let’s add credentials of Tomcat users to deploy our web application:
  • Choose “System” in the credentials context:

Screenshot illustrating Choose “System” in the credentials context:
  • Choose “Global” which are credentials that available to all jobs, agents, and users across the entire Jenkins instance:

Screenshot illustrating entire Jenkins instance:
Screenshot illustrating entire Jenkins instance:
  • Remember that we have an admin user of Tomcat to have a “manager-script” role so this specific “admin” user can run script from one instance to manage another instance (from Jenkin Server to Tomcat Server):

Screenshot illustrating Jenkin Server to Tomcat Server):
Screenshot illustrating Jenkin Server to Tomcat Server):
Screenshot illustrating Jenkin Server to Tomcat Server):
  • Now, you should have the credentials like so:

Screenshot illustrating Now, you should have the credentials like so:
  • Nice, now we are ready to create a new Jenkins job to build and deploy on Tomcat Server:

Screenshot illustrating Nice, now we are ready to create a new Jenkins job to build and deploy on Tomcat Server:
  • Please fill in the details of this job:

    • Description:

Screenshot illustrating Description:
  • Git:

Screenshot illustrating Git:
  • Maven Build:

Screenshot illustrating Maven Build:
  • Post-build Actions (Things happens after building completion):

Screenshot illustrating Post-build Actions (Things happens after building completion):
Screenshot illustrating Post-build Actions (Things happens after building completion):
Screenshot illustrating Post-build Actions (Things happens after building completion):
  • We are done with the configurations of that Jenkins job:

Screenshot illustrating We are done with the configurations of that Jenkins job:
  • It’s time to build and deploy with our new Jenkins job:

Screenshot illustrating It’s time to build and deploy with our new Jenkins job:
  • Let’s look at the build log and try to understand it:

Screenshot illustrating Let’s look at the build log and try to understand it:
Screenshot illustrating Let’s look at the build log and try to understand it:
Screenshot illustrating Let’s look at the build log and try to understand it:
  • Alright, it seems alright! Git pull -> Maven Build -> Deploy on Tomcat done! Let’s check the website:

Screenshot illustrating website:

Super glorious! We love to see that!

  • You can login as Tomcat admin to check out the Manager App to see if your War file is in the webapps directory:

Screenshot illustrating webapps directory:
  • That’s pretty awesome!

Auto-deployment with Poll SCM to trigger build when pushing a new Github commit

  • However, there is one more thing we want to do is that the build process on Jenkins should be automated instead of manual as we still need to click on the build button for this Jenkins job to run!

Screenshot illustrating job to run!
  • That’s why let’s go back to this job and modify its configuration:

Screenshot illustrating That’s why let’s go back to this job and modify its configuration:
  • Add the schedule like “* * * * *” to the Poll SCM which is going to be an expensive operation.

Screenshot illustrating Add the schedule like “* * * * *” to the Poll SCM which is going to be an expensive operation.

That’s it! Your task now is to test if this works:

  • Git clone the public repository to your laptop/computer.

  • Modify the index.jsp file to add some lines.

  • Git add, commit and push that change to your Github repo. (To do that, you need to use Personal Access Code of Github or setup SSH keys for Github) (Or if you just want to quickly test, you can edit file and commit directly on the Github repo website)

  • Then check the build history of BuildAndDeploy job to see if there is any build trigger automatically whenever you push a new change to your Github repo.

Screenshot illustrating automatically whenever you push a new change to your Github repo. (1 of 2)Screenshot illustrating automatically whenever you push a new change to your Github repo. (2 of 2)

Alright! That’s pretty cool for a nice automation from Development ➜ Commit and Push to Github ➜ Jenkins pulls the new version of your code on Github ➜ Jenkins build the new artifacts of the project using Maven ➜ Jenkins deploy that artifacts on Tomcat server ➜ Customers can see the new features of the website immediately with no downtime!

Screenshot illustrating features of the website immediately with no downtime!

Congratulations for building your first basic CI/CD pipeline using Jenkins!

[Important Note] Please do not delete the Jenkins server after you finish this week's tutorial as we still need it for next week's tutorial with Docker! Otherwise, you might need to set up the Jenkins server all over again to follow the next week's tutorial!

🧪 Challenge 1: Trigger Jenkins with GitHub webhooks

  • Poll SCM is very easy to set up as it does not require additional integration or setup outside Jenkins. However, it is quite inefficient as Jenkins continuously checks if there is any new change of the repository, even when no changes are made. As a result, this consumes more resources, especially when polling frequently or with large repositories.

  • GitHub Hook Trigger for GITScm Polling is more efficient as there is no periodic polling; Jenkins acts only when notified of changes (real-time triggers). As a result, it reduces unnecessary load on both Jenkins and Git servers. However, it has more complex steps to set up as it requires GitHub repository admin rights to set up webhooks.

Screenshot illustrating up as it requires GitHub repository admin rights to set up webhooks.

Instead of using Poll SCM, can you try to use the “GitHub hook trigger for GITScm polling” option to trigger builds efficiently?

Here are some step by step guidance to set it up:

  • Configure GitHub Repository:

    • Go to your repository on GitHub.

    • Navigate to Settings > Webhooks.

    • Click on Add webhook.

      • Payload URL : Use http://<JENKINS_URL>:<PORT>/github-webhook/ (replace <JENKINS_URL> and <PORT> with your Jenkins URL and port).

      • Content type : Select application/json.

      • Secret : Leave blank (optional).

      • SSL verification : Enable.

      • Trigger events : Select Just the push event.

Screenshot illustrating Trigger events : Select Just the push event.
  • Install Required Jenkins Plugins

    • GitHub Plugin (if not yet installed)

Screenshot illustrating GitHub Plugin (if not yet installed)
  • Enable GitHub Hook Trigger in Jenkins Job

    • Select GitHub hook trigger for GITScm polling for the Jenkins job!

Screenshot illustrating Select GitHub hook trigger for GITScm polling for the Jenkins job!
  • Test the Webhook

    • Go back to your GitHub repository settings.

    • Under Webhooks, click on your newly created webhook.

    • Click Redeliver to send a test payload to Jenkins.

Screenshot illustrating Click Redeliver to send a test payload to Jenkins.
  • Go to Jenkins Dashboard > Manage Jenkins > System Log.

Screenshot illustrating Go to Jenkins Dashboard > Manage Jenkins > System Log.
Screenshot illustrating Go to Jenkins Dashboard > Manage Jenkins > System Log.
  • Verify that the webhook payload is received by Jenkins.

  • Test with a real Commit

    • Go to the Github repo

    • Make a change and commit

    • Check your Jenkins job to see if the build is triggered automatically.

    • In the log of the build triggered by Github Webhook, you should see this:

Screenshot illustrating In the log of the build triggered by Github Webhook, you should see this:

🧪 Challenge 2: Authenticate a private repository with a GitHub PAT

Objective: In the tutorial so far, to keep it simple, you have been working with a public Github repo. However, in real-life projects, most of the company projects are in private repos.

When working with private GitHub repositories, Jenkins needs proper authentication credentials to access the repository. This challenge guides you through setting up Jenkins to securely pull code from a private repository.

󰠁 Before You Start: Create Your Own Private GitHub Classroom Repo

If you don’t already have a private GitHub repository, follow the instructions in the Github Classroom Guide on your course page to create one. This is also good practice for your upcoming in-class test.

Screenshot illustrating Guide on your course page to create one. This is also good practice for your upcoming in-class test.

⚠ Reminder: Your GitHub repository must be private to simulate real-world CI/CD scenarios and prepare you for the exam.

📦 After receiving your private GitHub Classroom repo:

  • Add some files to your repo (e.g., a simple README or .java files), or upload a sample Maven Web Project.

  • This will allow you to verify later that Jenkins can clone or pull the repository contents successfully when configured.

🔧 Step-by-Step Instructions:

  • Step 1: Generate classic Personal Access Token (PAT) from GitHub

    • Select scopes:

      • repo ( Full control of private repositories)

      • admin:repo_hook (To read repo webhooks)

      • deplete_repo (Delete repositories)

Screenshot illustrating deplete_repo (Delete repositories)
  • Step 2: Add GitHub Credentials to Jenkins

    • Manage Jenkins > Credentials > System

    • The credentials (e.g., Global credentials), click Add credentials.

      • Kind: Username with password.

      • Username: Your GitHub username.

      • Password: Paste the generated PAT here.

      • ID: Enter a recognizable ID like github-private-repo-credentials.

      • Description: Add an optional description (e.g., "GitHub PAT for private repositories").

Screenshot illustrating repositories").
Screenshot illustrating repositories").
  • Step 3 : Configure Jenkins Job to Use the Credentials

    • Under Source Code Management, select Git.

    • Click on Credentials and select the credential ID you created (github-private-repo-credentials).

Screenshot illustrating (github-private-repo-credentials).
  • Step 4 : Test the Configuration

    • Build the Jenkins job.

    • Check the build log:

      • If successful, you should see Jenkins fetching the repository code.

      • If there’s an error, ensure the PAT has the correct permissions and was copied correctly.

Screenshot illustrating copied correctly.

Notes:

  • For security, never expose your Personal Access Token in job logs or configuration files.

  • If your team uses SSH for GitHub authentication, you can configure Jenkins with an SSH private key instead (you should research how to setup SSH private key instead of PAT for more secure Github authentication)

🧪 Challenge 3: Authenticate a private repository with SSH

Objective : In a professional environment, SSH key pairs are often used to securely authenticate Jenkins with external services like GitHub. Your task is to set up SSH key-based authentication for Jenkins and use it to securely pull code from a private GitHub repository.

Here are some general steps for your hints:

  • Generate SSH Key Pair for Jenkins

    • SSH into the Jenkins server (EC2 Instance 1).

    • Generate an SSH key pair for Jenkins using the following command:

      • ssh-keygen -t rsa -b 4096 -C "your-email@your-company.com"

    • Press Enter to save the key to the default location (~/.ssh/id_rsa) and skip the passphrase by pressing Enter again.

    • Pay attention to the location of these public and private key files:

      • Private Key: ~/.ssh/id_rsa

      • Public Key: ~/.ssh/id_rsa.pub

Screenshot illustrating Public Key: ~/.ssh/id_rsa.pub
  • Add the Public Key to GitHub

    • Copy the public key content:

      • cat ~/.ssh/id_rsa.pub

    • Go to GitHub:

      • Navigate to Settings > SSH and GPG Keys.

      • Click New SSH Key.

      • Paste the copied key content and save it.

Screenshot illustrating Paste the copied key content and save it.
  • Add the Private Key to Jenkins

    • Access the Jenkins dashboard and navigate to: Manage Jenkins > Manage Credentials > (Global) > Add Credentials.

    • Select the credential type SSH Username with Private Key and configure it:

Screenshot illustrating Select the credential type SSH Username with Private Key and configure it:
  • Username: git

    • Private Key: Select Enter directly and paste the private key content:

      • cat ~/.ssh/id_rsa

      • ID: Use an easily recognizable ID, such as ssh-key-github.

      • Description: Add a description like SSH Key for GitHub.

Screenshot illustrating Description: Add a description like SSH Key for GitHub.
  • Update Jenkins Git Host Key Verification Strategy

    • Jenkins is enforcing strict host key verification, and you need to configure it appropriately to make it work for the purpose of testing!

    • Go to Manage Jenkins > Security

Screenshot illustrating Go to Manage Jenkins > Security
  • Choose No host key verification temporarily for testing (not recommended for production environments).

Screenshot illustrating production environments).
  • Configure Jenkins Job with SSH-based GitHub Repository URL

    • Go to your Jenkins job settings.

    • Under Source Code Management, select Git.

    • Enter the repository URL in SSH format:

      • git@github.com:username/private-repo.git

    • In the Credentials field, select the SSH credentials (ssh-key-github) you added earlier.

  • Test the Configuration

    • Save the Jenkins job configuration.

    • Trigger a build for the job.

    • Verify in the build logs that Jenkins successfully clones the private repository.

Screenshot illustrating Verify in the build logs that Jenkins successfully clones the private repository.
  • Troubleshooting Tips (if something goes wrong)

    • If the build fails with permission errors:

      • Ensure the SSH key is correctly added to your GitHub account.

      • Verify that the GitHub repository URL uses the git@github.com format.

    • Test the connection from the Jenkins server to GitHub:

      • ssh -T git@github.com

      • You should see a success message indicating a successful authentication.

[Question] Why is SSH key-based authentication preferred over Personal Access Tokens (PATs) for Jenkins in CI/CD pipelines?

🧪 Challenge 4: Stop deployment when tests fail

Objective : Ensure that the CI/CD pipeline halts the deployment process if a critical test (such as verifying the presence of an HTML component) fails. This challenge demonstrates how to add automated validation as a gatekeeper in your Jenkins pipeline and prevent faulty code from being deployed to production.

Problem Statement: In a typical CI/CD pipeline, automated testing ensures code quality before deployment. If a test fails, the deployment process should stop to prevent incomplete or faulty features from reaching the server. Your task is to:

  • Integrate a test step into the Jenkins pipeline to validate the presence of an expected HTML component in the index.html file (e.g., <h1>DevOps</h1>).

  • Stop the deployment to a Tomcat server if the test fails.

  • Notify the development team when the deployment is blocked due to a failed test.

Steps to Complete the Challenge

  • Modify your existing Jenkins job to include a testing stage before the deployment stage:

    • Add a Test Step: Build Step > Execute Shell.

    • Enter the following script to test if an HTML component exists:

      • This script checks for a title element in the index.html file. Adjust the search term in the grep command as needed.

      • exit 1 ensures the build step fails if the HTML component is not found or the index.jsp file is missing. Jenkins interprets any non-zero exit code as a failure, which marks the build as FAILED, which will prevent subsequent stages like deployment.

# Navigate to the cloned repository's location
cd $WORKSPACE
# Check if index.html exists
if [ ! -f src/main/webapp/index.jsp ]; then
  echo "Error: index.jsp not found!"
  exit 1
fi
# Search for a specific HTML component
if grep -q "<title>Hello DevOps Students!</title>" src/main/webapp/index.jsp; then
  echo "HTML component found!"
else
  echo "Error: HTML component not found!"
  exit 1
fi
  • [Optional] Configure a notification system (e.g., email or Slack) to alert the team about the failure. Use the Email Notification Plugin or Slack Plugin for this purpose.

  • Test the Pipeline:

    • Modify the index.jsp file in your Github repository to intentionally miss the required HTML component.

    • Commit and push the changes to your GitHub repository.

    • Trigger the pipeline and verify:

      • The pipeline stops at the testing stage with a failure.

      • Notifications are sent to the team about the failure.

    • Restore the correct index.jsp file, commit, and push again. Ensure the deployment proceeds successfully.

Screenshot illustrating proceeds successfully.

Success build log screenshot:

Screenshot illustrating Success build log screenshot:

Fail build log screenshot:

Screenshot illustrating Fail build log screenshot:

📝 Jenkins security and networking notes

This is a naive example of testing, intended purely for learning purposes. While the simple grep command demonstrates how to implement basic validations in Jenkins, it is not sufficient for real-world web application testing. For robust and scalable testing in real-world applications, consider the following:

  • Selenium : For browser-based automation and end-to-end testing.

  • JUnit/TestNG : For unit and integration testing in Java applications.

  • Mockito : For mocking dependencies during Java tests.

  • Spring Boot Test Tools : For REST API and service layer testing.

  • JaCoCo : For code coverage analysis.

  • Cypress/Playwright : Modern alternatives to Selenium for end-to-end testing.

  • Jenkins Plugins : Use plugins like JUnit, Selenium, and JaCoCo to integrate test results into your pipeline.

These tools enhance testing for web applications, ensuring reliability and production-readiness.

Extra Reading:

  • Setup CI/CD Pipeline with Jenkins by using AWS CodeBuild and AWS CodeDeploy

Screenshot illustrating Setup CI/CD Pipeline with Jenkins by using AWS CodeBuild and AWS CodeDeploy

📚 Continue the course