Skip to content

Commit 8cff8c3

Browse files
committed
DevOps: Push DevOps-Project-18
* Jenkins Pipeline for Java based application using Maven, SonarQube, Argo CD, Helm and Kubernetes Signed-off-by: NotHarshhaa <[email protected]>
1 parent 4ad3c74 commit 8cff8c3

File tree

12 files changed

+385
-0
lines changed

12 files changed

+385
-0
lines changed

DevOps-Project-18/README.md

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Jenkins Pipeline for Java based application using Maven, SonarQube, Argo CD, Helm and Kubernetes
2+
3+
![](https://user-images.githubusercontent.com/43399466/228301952-abc02ca2-9942-4a67-8293-f76647b6f9d8.png)
4+
5+
6+
## 🔗 BLOG URL HERE: https://harshhaa.hashnode.dev/streamlining-cicd-workflow-with-github-jenkins-sonarqube-docker-argocd-and-gitops
7+
8+
9+
Here are the step-by-step details to set up an **end-to-end Jenkins pipeline for a Java application using SonarQube, Argo CD, Helm, and Kubernetes:**
10+
11+
**Prerequisites:**
12+
- Java application code hosted on a Git repository
13+
- Jenkins server
14+
- Kubernetes cluster
15+
- Helm package manager
16+
- Argo CD
17+
18+
**Steps:**
19+
20+
1. Install the necessary Jenkins plugins:
21+
1.1 Git plugin
22+
1.2 Maven Integration plugin
23+
1.3 Pipeline plugin
24+
1.4 Kubernetes Continuous Deploy plugin
25+
26+
2. Create a new Jenkins pipeline:
27+
2.1 In Jenkins, create a new pipeline job and configure it with the Git repository URL for the Java application.
28+
2.2 Add a Jenkinsfile to the Git repository to define the pipeline stages.
29+
30+
3. Define the pipeline stages:
31+
Stage 1: Checkout the source code from Git.
32+
Stage 2: Build the Java application using Maven.
33+
Stage 3: Run unit tests using JUnit and Mockito.
34+
Stage 4: Run SonarQube analysis to check the code quality.
35+
Stage 5: Package the application into a JAR file.
36+
Stage 6: Deploy the application to a test environment using Helm.
37+
Stage 7: Run user acceptance tests on the deployed application.
38+
Stage 8: Promote the application to a production environment using Argo CD.
39+
40+
4. Configure Jenkins pipeline stages:
41+
Stage 1: Use the Git plugin to check out the source code from the Git repository.
42+
Stage 2: Use the Maven Integration plugin to build the Java application.
43+
Stage 3: Use the JUnit and Mockito plugins to run unit tests.
44+
Stage 4: Use the SonarQube plugin to analyze the code quality of the Java application.
45+
Stage 5: Use the Maven Integration plugin to package the application into a JAR file.
46+
Stage 6: Use the Kubernetes Continuous Deploy plugin to deploy the application to a test environment using Helm.
47+
Stage 7: Use a testing framework like Selenium to run user acceptance tests on the deployed application.
48+
Stage 8: Use Argo CD to promote the application to a production environment.
49+
50+
5. Set up Argo CD:
51+
Install Argo CD on the Kubernetes cluster.
52+
Set up a Git repository for Argo CD to track the changes in the Helm charts and Kubernetes manifests.
53+
Create a Helm chart for the Java application that includes the Kubernetes manifests and Helm values.
54+
Add the Helm chart to the Git repository that Argo CD is tracking.
55+
56+
6. Configure Jenkins pipeline to integrate with Argo CD:
57+
6.1 Add the Argo CD API token to Jenkins credentials.
58+
6.2 Update the Jenkins pipeline to include the Argo CD deployment stage.
59+
60+
7. Run the Jenkins pipeline:
61+
7.1 Trigger the Jenkins pipeline to start the CI/CD process for the Java application.
62+
7.2 Monitor the pipeline stages and fix any issues that arise.
63+
64+
This end-to-end Jenkins pipeline will automate the entire CI/CD process for a Java application, from code checkout to production deployment, using popular tools like SonarQube, Argo CD, Helm, and Kubernetes.
65+
66+
# Thank you
67+
Thank you for taking the time to work on this tutorial/labs. Let me know what you thought!
68+
69+
#### Author by [Harshhaa Reddy](https://github.com/NotHarshhaa)
70+
71+
### Ensure to follow me on GitHub. Please star/share this repository!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: spring-boot-app
5+
labels:
6+
app: spring-boot-app
7+
spec:
8+
replicas: 2
9+
selector:
10+
matchLabels:
11+
app: spring-boot-app
12+
template:
13+
metadata:
14+
labels:
15+
app: spring-boot-app
16+
spec:
17+
containers:
18+
- name: spring-boot-app
19+
image: abhishekf5/ultimate-cicd:replaceImageTag
20+
ports:
21+
- containerPort: 8080
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: spring-boot-app-service
5+
spec:
6+
type: NodePort
7+
ports:
8+
- name: http
9+
port: 80
10+
targetPort: 8080
11+
protocol: TCP
12+
selector:
13+
app: spring-boot-app
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# You can change this base image to anything else
2+
# But make sure to use the correct version of Java
3+
FROM adoptopenjdk/openjdk11:alpine-jre
4+
5+
# Simply the artifact path
6+
ARG artifact=target/spring-boot-web.jar
7+
8+
WORKDIR /opt/app
9+
10+
COPY ${artifact} app.jar
11+
12+
# This should not be changed
13+
ENTRYPOINT ["java","-jar","app.jar"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
pipeline {
2+
agent {
3+
docker {
4+
image 'abhishekf5/maven-abhishek-docker-agent:v1'
5+
args '--user root -v /var/run/docker.sock:/var/run/docker.sock' // mount Docker socket to access the host's Docker daemon
6+
}
7+
}
8+
stages {
9+
stage('Checkout') {
10+
steps {
11+
sh 'echo passed'
12+
//git branch: 'main', url: 'https://github.com/iam-veeramalla/Jenkins-Zero-To-Hero.git'
13+
}
14+
}
15+
stage('Build and Test') {
16+
steps {
17+
sh 'ls -ltr'
18+
// build the project and create a JAR file
19+
sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && mvn clean package'
20+
}
21+
}
22+
stage('Static Code Analysis') {
23+
environment {
24+
SONAR_URL = "http://34.201.116.83:9000"
25+
}
26+
steps {
27+
withCredentials([string(credentialsId: 'sonarqube', variable: 'SONAR_AUTH_TOKEN')]) {
28+
sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && mvn sonar:sonar -Dsonar.login=$SONAR_AUTH_TOKEN -Dsonar.host.url=${SONAR_URL}'
29+
}
30+
}
31+
}
32+
stage('Build and Push Docker Image') {
33+
environment {
34+
DOCKER_IMAGE = "abhishekf5/ultimate-cicd:${BUILD_NUMBER}"
35+
// DOCKERFILE_LOCATION = "java-maven-sonar-argocd-helm-k8s/spring-boot-app/Dockerfile"
36+
REGISTRY_CREDENTIALS = credentials('docker-cred')
37+
}
38+
steps {
39+
script {
40+
sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && docker build -t ${DOCKER_IMAGE} .'
41+
def dockerImage = docker.image("${DOCKER_IMAGE}")
42+
docker.withRegistry('https://index.docker.io/v1/', "docker-cred") {
43+
dockerImage.push()
44+
}
45+
}
46+
}
47+
}
48+
stage('Update Deployment File') {
49+
environment {
50+
GIT_REPO_NAME = "Jenkins-Zero-To-Hero"
51+
GIT_USER_NAME = "iam-veeramalla"
52+
}
53+
steps {
54+
withCredentials([string(credentialsId: 'github', variable: 'GITHUB_TOKEN')]) {
55+
sh '''
56+
git config user.email "[email protected]"
57+
git config user.name "Abhishek Veeramalla"
58+
BUILD_NUMBER=${BUILD_NUMBER}
59+
sed -i "s/replaceImageTag/${BUILD_NUMBER}/g" java-maven-sonar-argocd-helm-k8s/spring-boot-app-manifests/deployment.yml
60+
git add java-maven-sonar-argocd-helm-k8s/spring-boot-app-manifests/deployment.yml
61+
git commit -m "Update deployment image to version ${BUILD_NUMBER}"
62+
git push https://${GITHUB_TOKEN}@github.com/${GIT_USER_NAME}/${GIT_REPO_NAME} HEAD:main
63+
'''
64+
}
65+
}
66+
}
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Spring Boot based Java web application
2+
3+
This is a simple Sprint Boot based Java application that can be built using Maven. Sprint Boot dependencies are handled using the pom.xml
4+
at the root directory of the repository.
5+
6+
This is a MVC architecture based application where controller returns a page with title and message attributes to the view.
7+
8+
## Execute the application locally and access it using your browser
9+
10+
Checkout the repo and move to the directory
11+
12+
```
13+
git clone https://github.com/NotHarshhaa/DevOps-Projects/DevOps-Project-18/sprint-boot-app
14+
cd DevOps-Project-18/sprint-boot-app
15+
```
16+
17+
Execute the Maven targets to generate the artifacts
18+
19+
```
20+
mvn clean package
21+
```
22+
23+
The above maven target stroes the artifacts to the `target` directory. You can either execute the artifact on your local machine
24+
(or) run it as a Docker container.
25+
26+
** Note: To avoid issues with local setup, Java versions and other dependencies, I would recommend the docker way. **
27+
28+
29+
### Execute locally (Java 11 needed) and access the application on http://localhost:8080
30+
31+
```
32+
java -jar target/spring-boot-web.jar
33+
```
34+
35+
### The Docker way
36+
37+
Build the Docker Image
38+
39+
```
40+
docker build -t ultimate-cicd-pipeline:v1 .
41+
```
42+
43+
```
44+
docker run -d -p 8010:8080 -t ultimate-cicd-pipeline:v1
45+
```
46+
47+
Hurray !! Access the application on `http://<ip-address>:8010`
48+
49+
50+
## Next Steps
51+
52+
### Configure a Sonar Server locally
53+
54+
```
55+
apt install unzip
56+
adduser sonarqube
57+
wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-9.4.0.54424.zip
58+
unzip *
59+
chmod -R 755 /home/sonarqube/sonarqube-9.4.0.54424
60+
chown -R sonarqube:sonarqube /home/sonarqube/sonarqube-9.4.0.54424
61+
cd sonarqube-9.4.0.54424/bin/linux-x86-64/
62+
./sonar.sh start
63+
```
64+
65+
Hurray !! Now you can access the `SonarQube Server` on `http://<ip-address>:9000`
66+
67+
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.abhishek</groupId>
8+
<artifactId>spring-boot-demo</artifactId>
9+
<version>1.0</version>
10+
11+
<name>spring-boot-demo</name>
12+
<url></url>
13+
14+
<parent>
15+
<groupId>org.springframework.boot</groupId>
16+
<artifactId>spring-boot-starter-parent</artifactId>
17+
<version>2.2.4.RELEASE</version>
18+
</parent>
19+
20+
<properties>
21+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
22+
<maven.compiler.source>11</maven.compiler.source>
23+
<maven.compiler.target>11</maven.compiler.target>
24+
<java.version>11</java.version>
25+
</properties>
26+
27+
<dependencies>
28+
29+
<dependency>
30+
<groupId>org.springframework.boot</groupId>
31+
<artifactId>spring-boot-starter-web</artifactId>
32+
</dependency>
33+
<dependency>
34+
<groupId>org.springframework.boot</groupId>
35+
<artifactId>spring-boot-starter-thymeleaf</artifactId>
36+
</dependency>
37+
<dependency>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-starter-test</artifactId>
40+
<scope>test</scope>
41+
</dependency>
42+
43+
<!-- debugging -->
44+
<dependency>
45+
<groupId>org.springframework.boot</groupId>
46+
<artifactId>spring-boot-devtools</artifactId>
47+
<optional>true</optional>
48+
</dependency>
49+
50+
</dependencies>
51+
52+
<build>
53+
54+
<finalName>spring-boot-web</finalName>
55+
56+
<plugins>
57+
<plugin>
58+
<groupId>org.springframework.boot</groupId>
59+
<artifactId>spring-boot-maven-plugin</artifactId>
60+
</plugin>
61+
<plugin>
62+
<groupId>org.apache.maven.plugins</groupId>
63+
<artifactId>maven-compiler-plugin</artifactId>
64+
<version>3.8.0</version>
65+
<configuration>
66+
<source>${java.version}</source>
67+
<target>${java.version}</target>
68+
</configuration>
69+
</plugin>
70+
71+
</plugins>
72+
</build>
73+
74+
75+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.abhishek;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.stereotype.Controller;
6+
import org.springframework.ui.Model;
7+
import org.springframework.web.bind.annotation.GetMapping;
8+
9+
@SpringBootApplication
10+
@Controller
11+
public class StartApplication {
12+
13+
@GetMapping("/")
14+
public String index(final Model model) {
15+
model.addAttribute("title", "I have successfuly built a sprint boot application using Maven");
16+
model.addAttribute("msg", "This application is deployed on to Kubernetes using Argo CD");
17+
return "index";
18+
}
19+
20+
public static void main(String[] args) {
21+
SpringApplication.run(StartApplication.class, args);
22+
}
23+
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# nothing here yet
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
body {
2+
padding-top: 5rem;
3+
}
4+
.starter-template {
5+
padding: 3rem 1.5rem;
6+
text-align: center;
7+
}

DevOps-Project-18/spring-boot-app/src/main/resources/static/js/main.js

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!DOCTYPE html>
2+
<html lang="en" xmlns:th="http://www.thymeleaf.org">
3+
<head>
4+
<meta charset="utf-8">
5+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"/>
6+
<link data-th-href="@{/css/main.css?{id}(id=${timestamp})}" rel="stylesheet">
7+
<title>CI/CD Master Class By Abhishek Veeramalla</title>
8+
</head>
9+
<body>
10+
11+
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
12+
<a class="navbar-brand" href="#">Ultimate CI/CD Pipeline using Java</div></a>
13+
</nav>
14+
15+
<main role="main" class="container">
16+
<div class="starter-template">
17+
<h1 th:text="${title}">Default title.</h1>
18+
<p th:text="${msg}">Default text.</p>
19+
</div>
20+
</main>
21+
22+
<script data-th-src="@{/js/main.js}"></script>
23+
</body>
24+
25+
</html>

0 commit comments

Comments
 (0)