End-to-End ultimate CI/CD Pipeline for Spring Boot Java application

End-to-End ultimate CI/CD Pipeline for Spring Boot Java application

Project Overview:

Project Overview: Implemented a comprehensive Jenkins Pipeline to automate the Continuous Integration (CI) and Continuous Deployment (CD) process for a Java based application. The pipeline leverages various tools, including Git, GitHub,Docker, Maven, SonarQube, Argocd and Kubernetes, to ensure seamless code delivery from development to production environments.

Tools Used:

GitHub,Docker, Maven, SonarQube, Argocd and Kubernetes

1)Create 2 EC2 instances:(Can be executed on single EC2 also)

1.t2.large

2.t2.medium(K8s and Argocd)

2)Source code checkouts:https://github.com/gsbarure/Jenkins-Zero-To-Hero.git

3)Install Jenkins and docker on EC2 instance.(Installations refer above repo)

4)for Admin password do cat var/lib/jenkins/secrets/initialAdminPassword

Once Jenkins is up,Set username and password(initial username/password-admin)

Here you go!

Jenkins stages:

Configure Jenkins pipeline stages:
    Stage 1: Use the Git plugin to check out the source code from the Git repository.
    Stage 2: Use the Maven Integration plugin to build the Java application.
    Stage 3: Use the JUnit and Mockito plugins to run unit tests.
    Stage 4: Use the SonarQube plugin to analyze the code quality of the Java application.
    Stage 5: Use the Maven Integration plugin to package the application into a JAR file.
    Stage 6: Use the Kubernetes Continuous Deploy plugin to deploy the application to a test environment using Helm.
    Stage 7: Use a testing framework like Selenium to run user acceptance tests on the deployed application.
    Stage 8: Use Argo CD to promote the application to a production environment.

5)Installed Plugins:Maven Integration,Docker Pipeline,Sonarqube scanner,Github integration,Kubernetes.

Now,Install maven,sonarqube(Please refer above repo for installations)

“mvn package” vs “mvn install”

The main difference between the “mvn package” and “mvn install” commands is that mvn package command will compile the source and will package it in its distributable formats, such as a JAR or WAR. The mvn install command, however, additionally to compiling the source code and packaging it into a JAR or a WAR, it will also install the package into the local repository, for use as a dependency in other projects locally.

6)Sonarqube:

SonarQube is a Code Quality Assurance tool that collects and analyzes source code, and provides reports for the code quality of your project.

7)for integration with Jenkins generate token:

8)Successful code Analysis by Sonarqube

9)Tried to duplicate the code:

10)Add credentials in Jenkins to integrate as secret text under manage Jenkins.

Lets move to Jenkins Pipeline:

Dockerfile:

# You can change this base image to anything else
# But make sure to use the correct version of Java
FROM adoptopenjdk/openjdk11:alpine-jre

WORKDIR /opt/app

COPY target/spring-boot-web.jar app.jar

# This should not be changed
ENTRYPOINT ["java","-jar","app.jar"]
pipeline {
    agent {
    docker {
      image 'abhishekf5/maven-abhishek-docker-agent:v1'
      args '--user root -v /var/run/docker.sock:/var/run/docker.sock' // mount Docker socket to access the host's Docker daemon
    }
  }
  stages {
    stage('Checkout') {
      steps {
        sh 'echo passed'
        git branch: 'main', url: 'https://github.com/gsbarure/Jenkins-Zero-To-Hero.git'
      }
    }
    stage('Build and Test') {
      steps {
        sh 'ls -ltr'
        // build the project and create a JAR file
        sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && mvn clean package'
      }
    }
    stage('Static Code Analysis') {
      environment {
        SONAR_URL = "http://100.25.118.160:9000"
      }
      steps {
        withCredentials([string(credentialsId: 'sonarqube', variable: 'SONAR_AUTH_TOKEN')]) {
          sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && mvn sonar:sonar -Dsonar.login=$SONAR_AUTH_TOKEN -Dsonar.host.url=${SONAR_URL}'
        }
      }
    }
    stage('Build and Push Docker Image') {
      environment {
        DOCKER_IMAGE = "gajananbarure/ultimate-cicd:${BUILD_NUMBER}"
        // DOCKERFILE_LOCATION = "java-maven-sonar-argocd-helm-k8s/spring-boot-app/Dockerfile"
       // REGISTRY_CREDENTIALS = credentials('docker-cred')
      }
      steps {
        script {
            sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && docker build -t ${DOCKER_IMAGE} .'
            def dockerImage = docker.image("${DOCKER_IMAGE}")
        withCredentials([usernamePassword(credentialsId:'dockerhub', passwordVariable:'dockerhubpassword', usernameVariable:'dockerhubuser')]) {
                                  sh "docker login -u ${env.dockerhubuser} -p ${env.dockerhubpassword}"
                                  sh 'docker push "${DOCKER_IMAGE}"'


        }
      }
    }
  }

Image pushed to dockerhub:

Now lets move to Kubernetes and argocd part

11)Minikube installations:https://minikube.sigs.k8s.io/docs/start/

12)Argocd installations:https://operatorhub.io/

Create basic argocd.yml file for deployment with argocd.

13)edit your service--example-argocd and change the service as NodePort

14)Here is the Service:

Try to access this service through web,to access we have to forward this port so that we can access argocd thru this port.

kubectl port-forward --address 0.0.0.0 svc/example-argocd-server 32002:80

15)Argocd:

Argo CD is a Kubernetes controller, responsible for continuously monitoring all running applications and comparing their live state to the desired state specified in the Git repository.

for 1st time access user Admin as username and password.

Rollback the application

Once you have identified the current version of the application, you can roll back to a previous version. To do this, follow the steps below:

  1. Navigate to the ArgoCD web UI and select the application you want to rollback.

  2. In the Application Overview page, click on the "REVISION HISTORY" section.

  3. Find the revision you want to rollback to and click on the "ROLLBACK" button next to it.

  4. In the confirmation dialog box, click "ROLLBACK" to confirm the rollback.

After the rollback process is complete, the application will be reverted to the previous version.

Complete Pipeline:

pipeline {
    agent {
    docker {
      image 'abhishekf5/maven-abhishek-docker-agent:v1'
      args '--user root -v /var/run/docker.sock:/var/run/docker.sock' // mount Docker socket to access the host's Docker daemon
    }
  }
  stages {
    stage('Checkout') {
      steps {
        sh 'echo passed'
        git branch: 'main', url: 'https://github.com/gsbarure/Jenkins-Zero-To-Hero.git'
      }
    }
    stage('Build and Test') {
      steps {
        sh 'ls -ltr'
        // build the project and create a JAR file
        sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && mvn clean package'
      }
    }
    stage('Static Code Analysis') {
      environment {
        SONAR_URL = "http://100.25.118.160:9000"
      }
      steps {
        withCredentials([string(credentialsId: 'sonarqube', variable: 'SONAR_AUTH_TOKEN')]) {
          sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && mvn sonar:sonar -Dsonar.login=$SONAR_AUTH_TOKEN -Dsonar.host.url=${SONAR_URL}'
        }
      }
    }
    stage('Build and Push Docker Image') {
      environment {
        DOCKER_IMAGE = "gajananbarure/ultimate-cicd:${BUILD_NUMBER}"
        // DOCKERFILE_LOCATION = "java-maven-sonar-argocd-helm-k8s/spring-boot-app/Dockerfile"
       // REGISTRY_CREDENTIALS = credentials('docker-cred')
      }
      steps {
        script {
            sh 'cd java-maven-sonar-argocd-helm-k8s/spring-boot-app && docker build -t ${DOCKER_IMAGE} .'
            def dockerImage = docker.image("${DOCKER_IMAGE}")
        withCredentials([usernamePassword(credentialsId:'dockerhub', passwordVariable:'dockerhubpassword', usernameVariable:'dockerhubuser')]) {
                                  sh "docker login -u ${env.dockerhubuser} -p ${env.dockerhubpassword}"
                                  sh 'docker push "${DOCKER_IMAGE}"'


        }
      }
    }
  }
   stage('Update Deployment File') {
        environment {
            GIT_REPO_NAME = "Jenkins-Zero-To-Hero"
            GIT_USER_NAME = "gsbarure"
        }
        steps {
            withCredentials([string(credentialsId: 'github', variable: 'GITHUB_TOKEN')]) {
                sh '''
                    git config user.email "gajananbarure@gmail.com"
                    git config user.name "Gajanan Barure"
                    BUILD_NUMBER=${BUILD_NUMBER}
                    sed -i "s/replaceImageTag/${BUILD_NUMBER}/g" java-maven-sonar-argocd-helm-k8s/spring-boot-app-manifests/deployment.yml
                    git add java-maven-sonar-argocd-helm-k8s/spring-boot-app-manifests/deployment.yml
                    git commit -m "Update deployment image to version ${BUILD_NUMBER}"
                    git push https://${GITHUB_TOKEN}@github.com/${GIT_USER_NAME}/${GIT_REPO_NAME} HEAD:main
                '''
            }
        }
    }
}
}

16)Update the Deployment.yml file and check if deployment triggered or not in argocd.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-boot-app
  labels:
    app: spring-boot-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-boot-app
  template:
    metadata:
      labels:
        app: spring-boot-app
    spec:
      containers:
      - name: spring-boot-app
        image: gajananbarure/ultimate-cicd:51
        ports:
        - containerPort: 8080

Successful execution..!!

Access your service now,Here we go!

***Finally!!!***✔️✔️

Code availability(GitHub):https://github.com/gsbarure/Jenkins-Zero-To-Hero.git

Linkdin:https://www.linkedin.com/in/gajanan-barure-7351a4140

***Happy Learning :)***✌✌

Keep learning,Keep growing🎇🎇

Thank you for reading!! Hope you find this helpful.