Continuous Integration Using Jenkins, Nexus, SonarQube, Slack
Continuous Integration with Jenkins
Table of contents
- Benefits
- Tools used
- Goals Achieved
- Workflow
- Flow of Execution
- Detailed Description of Steps to follow
- Launch EC2 instances
- Post installation of Jenkins
- Post installation of Nexus
- Nexus Integration Job
- Slack Integration
- Unit Tests, Code Analysis with Sonarqube
- Nexus Repository Integration
- Create a Different View of the Pipeline
- Complete Flow
Source Code for this integration is present in this GitHub Repository
Benefits
Short MTTR - Mean Time to Repair
Fault Isolation
Agile
No Human Intervention Required
Tools used
Jenkins
GIT
Maven
Checkstyle
Slack
Sonatype Nexus
Sonarqube
AWS EC2
Goals Achieved
Fast TAT on Feature changes
Less Disruptive
Workflow
The below flowchart illustrates, how the code passes through every stage.
Developers Commits the Code into GIT(Source Code Management). This application is built on Java, so we are using Maven as build tool.
Jenkins fetches the code and builds(compiles) it, runs Unit Tests on it and write the outcome as a notification in Slack/Teams.
Next it runs the Code Analysis using Sonarqube and puts the code through Quality Gates and if it passes the quality thresholds it will send the notification to Slack/Teams.
If it is not passing the quality thresholds - It will be passed to Developer to fix the bugs and the process begins from scratch.
After passing through Code Analysis, the artifact will be packaged and uploaded to the artifact repository that is Nexus and a notification will be sent through Slack/Teams.
Flow of Execution
Login to AWS Account
Create login key
Create Security Group
(i). Jenkins
(ii). Nexus
(iii). Sonar
Create EC2 instances with user data
(i). Jenkins
(ii). Nexus
(iii). Sonar
Jenkins Post Installation
Nexus Repository Setup
SonarQube post installation
Jenkins Steps
(i). Build Job
(ii). Setup Slack Notification
(iii). Check style Code Analysis Job
(iv). Setup Sonar integration
(v). Sonar code analysis job
(vi). Artifact upload Job
Connect all jobs together with BuildPipeline
(i). Set Automatic Build Trigger
Test with VSCode or Intellij
Detailed Description of Steps to follow
Login into AWS Management Console. Open the EC2 Pane.
Before creating the EC2 instances, we need to create Key pairs and Security Groups for the EC2 instances.
EC2 —> Key pairs
(i). Give a name for the key pair
(ii). File format - .pem
EC2 Security Groups
(i). Give names for security group
dprofile-jenkins-sg
dprofile-nexus-sg
dprofile-sonar-sg
dprofile-jenkins-sg
Provide the Group Name (dprofile-jenkins-sg) and Short Description.
Create Inbound Rules –
Port 8080 and 22 from the machine IP address, where you will manage the instances. All Traffic or Port 80 from SonarQube security group (Allow Sonar to access Jenkins for quality gates result)
Create Outbound Rules –
Allow All traffic
dprofile-nexus-sg
Provide the Group Name (dprofile-nexus-sg) and Short Description.
Create Inbound Rules –
Port 8081 and 22 from the machine IP address, where you will manage the instances. Source Port (8081) from Jenkins Security Group - To allow the upload of artifacts
Create Outbound Rules –
Allow All traffic
dprofile-sonar-sg
Provide the Group Name (dprofile-sonar-sg) and Short Description.
Create Inbound Rules –
Port 8081 and 22 from the machine IP address, where you will manage the instances. Source Port Range (8081) from Jenkins Security Group - To allow the upload of artifacts
Create Outbound Rules –
Allow All traffic
We have to create tags in Security Groups page.
javaprofile-jenkins-sg
javaprofile-nexus-sg
javaprofile-sonar-sg
Launch EC2 instances
Provision the instances using userdata. Start with Jenkins instance
Github —> UserData Folder —> jenkins-setup.sh, nexus-setup.sh and sonar-setup.sh
Clone the Github repository —> ci-jenkins. After cloning, always run “git pull” to update the latest changes. Switch to the branch —> “git checkout ci-jenkins”
Navigate to “userdata” folder. Shell scripts are available to create the EC2 instances for Jenkins, Nexus and Sonarqube
Install all roles using Ubuntu 22.04.
AWS Portal —> EC2 —> Launch an instance —> Select t2.small (which will have some charges)
Fill the details. Under Advanced Details section —> User Data —> fill it with the shell script for nexus from userdata. Repeat the steps 5 and 6 for Jenkins and Sonarqube servers
Provide proper tags to identify the instances
Name – Nexus Server
Project – Javaprofile
Select the respective security groups and security key pairs created in the beginning of this tutorial.
Post installation of Jenkins
- To complete post installation of Jenkins, access the Jenkins portal with <public IP>:8080
To get the initial password for administrator account, we need to access the server through SSH with default user name “ubuntu” and with the key file to login into the AWS CLI
Switch to root user – “sudo -i”
To get the password – open the file “cat /var/lib/jenkins/secrets/initialAdminPassword
Paste the password into the portal and continue the setup
- Select “Install suggested plugins”
- Create the Admin User
Confirm Instance Configuration and complete the installation.
Before we configure a job, we need to perform Nexus repository.
Post installation of Nexus
Access the VM with the public IP address with port 8081. <public ip>:8081
To sign in, we need to SSH into the Nexus VM with the key file and the default user is “admin”
The password is in the file “/opt/nexus/sonatype-work/nexus3/admin.password”.
Post installation wizard opens. Follow the instructions to finish the post installation steps.
We need to create three maven repositories. Administration —> Repository —> Repositories —> Create Repository
(i). Select maven2(hosted) javaprofile-release (This repository will have artifacts which are well tested and deployed to servers)
(ii). Select maven2(proxy) javaprofile-maven-central. We have provide the remote repository address to download all dependencies (This repository will have all the dependencies downloaded from the maven public repository)
(iii). Select maven2(group) javaprofile-maven-group. Make the above two repositories as a member repositories under this group repository.
- We can create a snapshot repository (optional). Select maven2(hosted) and select “Snapshot” under Version Policy, Add this snapshot repository also to the “javaprofile-maven-group” as a member.
- To configure maven to download the dependencies and place those under “javaprofile-maven-central”, we need to configure the settings.xml. We will pass these variables from maven build job that we are going to configure as a Jenkins job.
Nexus Integration Job
Login into Jenkins - <publicip>:8080
Create a job
For this project, we are using “Freestyle Project”
- Give unique name for the project, description, provide the git url and branch name to fetch source code.
- In Build section, select “Invoke top-level Maven targets” and for goals mention “install -DskipTests”. This is will use the pom.xml file, which is already in the source code. For Settings, use the filesystem option and mention the path of the settings.xml file.
- Assign variables for the settings.xml.
- After configuring the variables, paste it under “properties”
- Save this job and build the job.
- Build job is successful.
Slack Integration
Build job is successful and the developers should be notified regarding this. So we are going to integrate with Slack to notify the developers and managers.
Create a slack account.
Create a workspace
Create a channel – provide a name and description as per requirement
Create an API for slack
Go to “api.slack.com” and click on “Start building”.
Click on “Create an app”, Give a name and select the workspace, and then “Create app”
Go to settings of the app and click on “Oauth & Permissions”
- Scroll down to see “Scopes” and under “Bot Token Scopes” add the permission for “calls:write”
- Scroll up and click on “Install App to Workspace”
You will be provided with a token. Copy the token and save it in the notepad.
We need to add the app into the channel and invite the app to the channel.
- To make use of the slack bot, we need to install a plugin in Jenkins. Head to Jenkins portal and click on “Manage Jenkins”
- Manage Jenkins —> Manage Plugins —> Available —> Search for “Slack” —> “Install without Restart”
- To configure the token, Navigate to Manage Jenkins —> Manage Credentials —> Store ‘Jenkins’ —> ‘Global Credentials’ —> Add Credentials —> Change the kind to “secret text”
- Now we will integrate with Slack with Jenkins. Navigate to Manage Jenkins —> Configure System —> Scroll to the end for Slack settings —> Put checkmark on “Custom Slack app bot user” and save the settings.
- Configure the job to send notifications.
- Navigate to “Post build Actions”
Click on Advanced, Enter the workspace name, credential (slack-token), channel/member id - #jenkins —> Test Connection.
Go back to slack channel and you would have got a notification.
Unit Tests, Code Analysis with Sonarqube
We are going to create a job in Jenkins called as “Test” and as a Freestyle Project and copy from the Build job that we created earlier.
In the Build phase, provide the goals as “test”, rest of the settings copied from “build” job.
Run the test job.
This test job should automatically run after the build job, so to configure this, Navigate to “Build” job —> Configure —> “Build” Tab —> Add post-build action —> Select “Build Other projects” —> Projects to build as “Test”.
Configure Integration job. Freestyle Job —> “Build Environment” tab —> Goals —> “verify -DskipUnitTests —> Rest of the settings comes from “Build” job.
This integration job should automatically run after the test job, so to configure this, Navigate to “Build” job —> Configure —> “Build” Tab —> Add post-build action —> Select “Build Other projects” —> Projects to build as “Integration Test”.
So upstream job is “Build” and downstream job is “Integration Test”
To perform simple code analysis, we have to install a plugin called “checkstyle”
Manage Jenkins —> Manage Plugins —> Available —> Search for “checks” —> Select “Checkstyle” and “Violations” —> “Install without Restart”.
Checkstyle will analyze the code and give the report. If the failures goes beyond threshold defined by quality gates, Violations will make the job unstable, so it won’t be promoted to next step.
Create a job in Jenkins for code analysis. Create new job and copy the settings of build job. For goals, enter “checkstyle:checkstyle”.
Configure “Post Build Actions” —> “Publish Checkstyle analysis results
- Run the job and results will be saved in the workspace.
Create a new job as “Code_Analysis” and copy the settings of “Build” job
In “Build Environment” tab à Invoke top-level Maven targets à Goals “checkstyle:checkstyle”.
- If you want to perform the Quality Gates checks for the source code in a different branch Under “Source Code Management” —> Select “Git” —> Enter Repository Url —> Then “Branch Specifier”.
If you want to perform the quality checks for code in the branch, either create a settings.xml file in the branch or use the default maven settings.
Under build tab, we configure the violations and stop the code to get promoted to next level if the quality checks are not passed.
- After configuring and testing the job, we can integrate the job. Jenkins Home —> Configure —> Integration Test —> Make the “Code_Analysis” job as the downstream job of “Integration Test” job using Post Build Actions.
Now we are going to analyse the code with checkstyle
Run the “Code Analysis” job to the publish the results
- Click “Console Output” and there we can find the location of the published results in .xml format.
We can find this checkstyle-result.xml in our Code Analysis job’s workspace.
Under Workspace, we can see the result.xml.
We get a graph with the data from violations in checkstyle-result.xml, the graph shows the violations between first job and second job. If we have fixed some violations, we will see a decrease in this graph.
We are going to give the checkstyle-result.xml file for scanning. In Post Build Action —> Add post-build section —> Report violations.
We can use other code analysis tools as you see in the below screenshot like “codenarc”, “cpd” etc. But for our use case we are using “checkstyle”.
According to the organization’s policies, we can set the toleration. In our new case, we have set the maximum toleration to 100.
We have tested the “Code Analysis” Job and now we can configure this job as a downstream job for “Integration Tests” job.
We now have four jobs connected with each other. First is Build, Second is Test, Third is Integration Test and the last one will be Code_Analysis
We have one more code analysis with Sonarqube and we are going to publish the results from checkstyle and sonarqube to Sonarqube dashboard.
We should have Sonarqube server up and running. We will access this server using its public IP address through port 80 with a browser.
Default username is admin and password is admin. Before putting it into production, change to a strong password. After logging in, you can see the projects page.
To integrate Jenkins with Sonarqube, Jenkins needs to authenticate to Sonarqube Server, for that we need to generate a token.
Top right corner —> Click the profile —> My Account —> Security —> Enter a token name and click on Generate. Copy the token and keep it safe to configure Jenkins.
- Login into Jenkins à Manage Plugins.
Click on “Available” Tab —> Search for “sonar” —> Select “SonarQube Server” and “Sonar Quality Gates” —> Install without Restart.
Manage Jenkins —> Global Tool Configuration —> Scroll down to “SonarQube Scanner” —> Click on “Add SonarQube Scanner”.
Select the version and provide the name for the scanner.
Manage Jenkins —> Configure System —> Look for “SonarQube Servers” —> Put checkmark on “Enable Injection” then Click on “Add SonarQube”.
Provide name and server URL. We can get the sonar server’s IP address from the EC2 Dashboard —> Instances —> Private IP Address —> Since we are running nginx, the default port is 80. Add the URL and add the token through credential manager.
Add the credentials through credentials provider. We have to copy the token that we created in Step 35.
The above setting configured to push Sonarqube results to server. But make the code go through Quality Gates, we have configure the Quality Gates settings in the same job. Scroll further down to see the setting. Quality Gates – SonarQube and click on “Add Sonar Instance”.
Fill the details in the below form.
Now we have to create SonarQube Analysis job. Provide any name, Name: SonarScanner-CodeAnalysis —> Freestyle Project —> Copy the settings from Build Job —> Set the “Build” Goals as “Install” —> Add one more step for build —> Execute SonarQube Scanner.
We have to configure sonar analysis properties, with the code repo, name etc.
Save and Run the job. You will get slack notification after the build is over.
Login into Sonarqube server —> Projects —> You will see the Code analysis status below the repo name with Bugs, Vulnerabilities etc.
We can decide the quality gates to pass the code to next level. For that, we have to configure Quality Gates.
Click Create —> Provide a Name —> Add Condition —> Select Bugs under Reliability.
We have to set a value, in order to stop it from passing the quality gates. Here we are going to set it to 50.
Configure your repo with the newly created Quality gates. Repo —> Project Settings —> Quality Gates —> Select the quality gate we created.
After this, we have to configure the Post build job with Project key and Job Status when analysis fails to FAILED – The job will fail and if you configure it as UNSTABLE – The job will become unstable. Save the job.
Check the console output for the status of the job.
Nexus Repository Integration
After passing the Quality Gates, the .war file which is called as an artifact will be generated. This has to be uploaded to the Nexus Artifact Repository.
To integrate, we need the plugins to be installed. We need three plugins.
Nexus Artifact Uploader.
Copy Artifact (Since we already have the artifact, we just need to copy it).
Zentimestamp – For versioning.
Manage Jenkins —> Available tab —> Search for the above plugins and install it without restart.
We have to create a job to copy the artifact to Nexus. Head to Jenkins —> New Project —> Provide a Name —> Choose Freestyle Project —> We don’t need source code hence don’t copy settings from any job.
In the Build section —> Add Build Step —> Copy artifacts from another project —> Provide a name —> Select “Latest Successful Build” —> Copy only “**/*.war”.
Add build step —> Nexus Artifact Uploader —> Fill the details for Nexus Server —> For GroupId, provide QA or Testing, For Version provide “V$BUILD_ID”, For repository, we created a release repository, mention the name of the repository in the last field.
Scroll up and change the date pattern under General Tab.
Add Artifact —> ArtifactID as “$BUILD_TIMESTAMP”, Type as “war” and File name (war file name).
Add Slack Notification Settings as Post Build Job.
Create a Different View of the Pipeline
To design a different view of our pipeline execution, we need to install a plugin. Manage Jenkins —> Manage Plugins —> Available Tab —> Search for “Build Pipeline” —> Install without restart.
Home page —> My views —> Provide a “View Name” —> Select “Build Pipeline view”.
Select the first job in the Pipeline Flow —> Build (This job as all downstream jobs).
Display Options —> No of Displayed Builds – 5 —> Save the job.
You can see the below “Build Pipeline” view.
Click Run and you can see all the pipelines to be executed.
We need to configure Jenkins to fetch the code automatically from SCM (Source Code Management. For this, we need to configure the Build job.
Build Triggers —> Poll SCM —> This will be in cron job format —> This is configured to poll every minute and this is for testing purposes. Save the changes.
To test this perform a empty Git commit and find the pipeline running.
If you are doing this as a test, don’t forget to delete the EC2 instances.
Complete Flow
Happy DevOpsing !!!