Quay lại

Continuous Integration sử dụng Github, Jenkins, Nexus, Sonarqube, ECR, ECS, Slack - P2 Chuyên mục Devops    2025-02-05    4 Lượt xem    4 Lượt thích    comment-3 Created with Sketch Beta. 0 Bình luận

Welcome to the second phase of our Continuous Integration journey in the cloud! If you successfully navigated through the initial phase, pat yourself on the back, great job! If you’re feeling a bit lost, check out our previous guide here to catch up.
Now, let’s dive into the implementation phase. In this stage, we’ll be covering the following key components:

GitHub Integration:

  • Establish a GitHub repository and smoothly migrate your code.
  • Integrate GitHub with Visual Studio Code for collaboration and testing.

Build Job with Nexus Repository:

  • Create a build job that interacts with the Nexus Repository.

GitHub WebHook:

  • Set up GitHub WebHooks to automate triggering events and enhance the responsiveness of your CI pipeline.

SonarQube Server Integration:

  • Integrate SonarQube into your CI pipeline for advanced code quality analysis.
  • Elevate your software development process by identifying and addressing code issues early in the development lifecycle.

Nexus Artifact Upload Stage:

  • Implement a dedicated stage for uploading artifacts to Nexus, ensuring a centralized and efficient artifact management process.

Slack Notification:

  • Enhance collaboration and communication by setting up Slack notifications.
  • Keep your team informed about important CI pipeline events, fostering a more responsive and collaborative development environment.

Without further delay, Ladies and Gentlemen, shall we begin

The first step here is to set up our Version Control System. The Code repository we’ll be using is https://github.com/IfeanyiSam/vprofile-project. Owing to the fact that you can’t make changes in my repository, you’ll need to fork this repository into your own account. To do that, follow these steps;

  1. Ensure that you are logged into your GitHub account. Make sure you have set up your .gitconfig file and imported your public SSH key into your GitHub account.
  2. Navigate to the GitHub repository: https://github.com/IfeanyiSam/vprofile-project. In the top right corner of the page, click on the “Fork” button. This creates a copy of the repository in your GitHub account.

3. Navigate to the “CI-jenkins” branch, click on “code” and copy the SSH url. In VSCode, open the Source Control section, click on “Clone Repository,” and paste the copied URL. Choose a directory for the local repository and clone it. In VSCode, you can switch to different branches by clicking on the branch name in the bottom-right corner of the screen. Select the “CI-jenkins” branch or any other branch you need.

We have successfully completed the Git Code Migration from GitHub to our Local Machine.

Next, we’ll execute our initial build job and push the result to the Nexus repository. As a DevOps engineer, understanding the tools in the build process is important. We’ll create a basic pipeline code for building the artifact, utilizing Maven and OpenJDK as dependencies. Let’s simplify the process by adding the necessary tools to Jenkins, configuring required credentials, and then writing the pipeline code.

To set up tools in Jenkins, follow these steps:

  1. On the Jenkins web interface, go to “Manage Jenkins” and select “Tools.”
  2. In the “JDK Installations” section, click “Add JDK” and uncheck “Install automatically.”
  3. Name it as “OracleJDK17” and set the Java_Home path to “/usr/lib/jvm/java-1.17.0-openjdk-amd64,” where Linux stores the JDK application.
  4. In the “Maven Installations” section, click “Add Maven,” with “Install automatically” checked. Name it “MAVEN3” and select the latest version.
  5. Click “Save,” and Jenkins is now configured with the necessary tools.

To enable Maven to download dependencies from Nexus in our pipeline code, we need to authenticate Nexus from Maven by adding Nexus credentials in Jenkins. Follow these steps:

  1. On the “Manage Jenkins” page, click on “Credentials,” then “System,” and finally “Global credentials (restricted).”
  2. In the top right corner, click on “Add credentials.”
  3. Set the “Kind” to “Username with password.”
  4. Provide the username and password used for Nexus login (e.g., “admin” and “admin123” in my case).
  5. Assign an ID and Description (e.g., Nexuslogin). Remember these details as they will be mentioned in the pipeline.

These steps ensure that Jenkins has the necessary credentials to authenticate with Nexus during the Maven build process.

Now it is time to write the pipeline code. Open VScode and make sure you’re in the CI-jenkins branch. Select the “Jenkinsfile”, delete the content and write this;

pipeline {
agent any
tools {
maven "MAVEN3"
jdk "OracleJDK17"
}

environment {
SNAP_REPO = 'vprofile-snapshot'
NEXUS_USER = 'admin'
NEXUS_PASS = 'admin123'
RELEASE_REPO = 'vprofile-release'
CENTRAL_REPO = 'vpro-maven-central'
NEXUS_IP = 'server_priv_ip' #nexus server private ip
NEXUS_PORT = '8081'
NEXUS_GRP_REPO = 'vpro-maven-group'
NEXUS_LOGIN = 'nexuslogin'
}

stages {
stage('Build'){
steps {
sh 'mvn -s settings.xml -DskipTests install'
}

}
}
}

Save and commit the change to Github. To configure our first build job using the pipeline we just wrote, follow these steps on the Jenkins Home page:

  1. Click on “New Item” on the Jenkins Homepage.
  2. Give the job a name, e.g., vprofile-ci-pipeline. Then select "Pipeline" and click "OK."
  3. Scroll down to “Pipeline” and under “Definition,” select “Pipeline script from SCM.” Under “SCM,” choose “Git.”
  4. In your GitHub account, open “vprofile,” select and copy the SSH URL. Back in Jenkins, paste the URL in the “Repository URL” section.
  5. Under “Credentials,” select “Add” and click on “Jenkins.” Choose “SSH username with private key.” Provide an ID and Description, e.g., githublogin. For "Username," type "git." Under the private key, select "Enter directly" and provide the private key of your SSH key. Click "Add."
  6. On your terminal, SSH into the Jenkins server and run the following commands:
sudo -i
su - jenkins
git ls-remote -h <SSH-url-of-your-github-repo> HEAD

7. Back in Jenkins, in the Credentials section, select the newly created credential “githublogin.” The error prompt above should clear.

8. Scroll down and change the branch name to “ci-jenkins.” Then click on “Save.”

9. On the left side of the landing page, Click on “Build now”

The next step is to configure GitHub Webhook. The idea is for the build process to be triggered whenever there is a commit in the github repository. To configure the GitHub Webhook for automatic triggering of the build process upon a commit, follow these steps:

  1. Copy the Jenkins URL (e.g., http://11.22.33.44:8080)
  2. Go to your GitHub repository and navigate to the Repository settings.
  3. On the left side, locate “Webhooks” and click on it.
  4. Select “Add webhook.” You may be prompted to provide your account password.
  5. In the “Payload URL” box, paste the Jenkins URL in this format: http://11.22.33.44/8080/github-webhook/
  6. Under “Content type,” select “application/json.”
  7. Scroll down and click on “Add webhook.”

Now, the GitHub Webhook is configured, and your build process will be automatically triggered whenever there is a new commit in the GitHub repository.

Now, let’s test the webhook to see if it truly works. But before we make any commits, we have to reconfigure the Build Job to be triggered through webhooks. On the Build Job “vprofile-ci-pipeline”, select “configure”, scroll down to “build triggers” and checkmark “GitHub hook trigger for GITScm polling”.

On VScode, let’s add another step which archives the artifact, to our pipeline for the sole purpose of testing our build triggers.

pipeline {
agent any
tools {
maven "MAVEN3"
jdk "OracleJDK17"
}

environment {
SNAP_REPO = 'vprofile-snapshot'
NEXUS_USER = 'admin'
NEXUS_PASS = 'admin123'
RELEASE_REPO = 'vprofile-release'
CENTRAL_REPO = 'vpro-maven-central'
NEXUS_IP = '172.31.95.74'
NEXUS_PORT = '8081'
NEXUS_GRP_REPO = 'vpro-maven-group'
NEXUS_LOGIN = 'nexuslogin'
}

stages {
stage('Build'){
steps {
sh 'mvn -s settings.xml -DskipTests install'
}
post {
success {
echo 'Archiving'
archiveArtifacts artifacts: '**/*.war'
}
}

}
}
}

Save and commit to trigger the Build Job.

We’ll add some new stages for further testing of the application and also see more automated builds as a result of the configured webhook.

The next phase is to implement SonarQube into our pipeline. The reason for this implementation is because, the unit tests and checkstyle analysis generate reports (found in these files; surefire-reports and checkstyle-result.xml) which can’t be easily understood but SonarQube provides a more human-readable report after it’s test is implemented.

To integrate SonarQube into our pipeline, we’ll need to set up the SonarScanner tool in Jenkins and configure SonarQube credentials. Follow these steps:

  1. Log in to Jenkins and click on “Manage Jenkins.”
  2. Click on “Global Tool Configuration,” scroll down, and select “Add SonarQube Scanner” under the “SonarQube Scanner” section.
  3. Give the tool a name (e.g., sonarscanner). Stick to this name as it will be used in the pipeline. Select version 4.7, then click on "Save."
  4. Navigate to “System Configuration” and scroll down to the SonarQube section.
  5. Give it a name (e.g., sonarserver). Provide the server URL, which should be the private IP of the SonarQube server in this format: http://111.22.33.44
  6. Go to the SonarQube dashboard and click on the “Administrator” icon, then “My Account,” then “Security.” Give the token a name (e.g., jenkins), then click on "Generate." Copy the token.
  7. Go back to Jenkins, under “Server Authentication Token,” click on “Add.” Under “Kind,” select “Secret text,” paste the token in the “Secret” box, give it an ID and Description (e.g., sonartoken), then click on "Add." Select the token and click on "Save."

Now let’s write the Pipeline code. Open your VScode and add this piepline below.

pipeline {
agent any
tools {
maven "MAVEN3"
jdk "OracleJDK17"
}

environment {
SNAP_REPO = 'vprofile-snapshot'
NEXUS_USER = 'admin'
NEXUS_PASS = 'admin123'
RELEASE_REPO = 'vprofile-release'
CENTRAL_REPO = 'vpro-maven-central'
NEXUS_IP = '172.31.95.74'
NEXUS_PORT = '8081'
NEXUS_GRP_REPO = 'vpro-maven-group'
NEXUS_LOGIN = 'nexuslogin'
SONARSERVER = 'sonarserver'
SONARSCANNER = 'sonarscanner'
}

stages {
stage('Build'){
steps {
sh 'mvn -s settings.xml -DskipTests install'
}
post {
success {
echo 'Archiving'
archiveArtifacts artifacts: '**/*.war'
}
}

}

stage('Test') {
steps {
sh 'mvn -s settings.xml test'
}
}

stage('Checkstyle Analysis') {
steps {
sh 'mvn -s settings.xml checkstyle:checkstyle'
}
}

stage ('Sonar Analysis') {
environment {
scannerHome = tool "${SONARSCANNER}"
}
steps {
withSonarQubeEnv("${SONARSERVER}") {
sh '''${scannerHome}/bin/sonar-scanner -Dsonar.projectKey=vprofile \
-Dsonar.projectName=vprofile \
-Dsonar.projectVersion=1.0 \
-Dsonar.sources=src/ \
-Dsonar.java.binaries=target/test-classes/com/visualpathit/account/controllerTest/ \
-Dsonar.junit.reportsPath=target/surefire-reports/ \
-Dsonar.jacoco.reportsPath=target/jacoco.exec \
-Dsonar.java.checkstyle.reportPaths=target/checkstyle-result.xml'
''
}
}
}

}
}

After editing on your VScode, save, then commit and push to trigger the pipeline.

We can explore SonarQube by setting up Quality Gates which if not met, will cause the pipeline to fail. To do this;

  1. On the SonarQube Dashboard, click on “Quality Gates,” then “Create.” Give the quality gate a name, e.g., vprofileQG.
  2. To set rules, click on “Add Condition.” Check the radio button for “Overall Code,” select “Bugs” in the drop-down menu for “Quality Gate fails when,” then give a value, e.g., 10. This value should cause the build to fail if not met. Click on “Add Condition.”
  3. Go to the Vprofile project settings, then click on “Quality Gates.” Select the newly created quality gate, i.e., “VprofileQG.”
  4. Set up webhooks in the Sonar Server to send results back to Jenkins. Under “Project Settings,” select “Webhooks.” Click on “Create,” give the webhook a name, then provide the Jenkins private IP in the URL box in this format: http://111.22.33.44:8080/sonarqube-webhook. Click on "Create."
  5. Add a new stage to your Jenkinsfile to implement the SonarQube quality gate.

Make sure to commit and push these changes.

To ensure the Quality Gate passes, increase the Bugs value above 17 in the SonarQube Quality Gate settings. After this adjustment, manually trigger the Jenkins pipeline job to apply the updated Quality Gate. Since no code changes were made, this process ensures the Quality Gate reflects the modified conditions.

To complete the last stage of our pipeline, we need to upload the artifact to the Nexus Repository. The artifact is intended for the “vprofile-release” repository on Nexus. To maintain a professional naming convention, we installed the “Build Timestamp” plugin.

To configure this:

  1. Go to the system configuration page by clicking on “Manage Jenkins.”
  2. Scroll down until you find “Build Timestamp.”
  3. Toggle the pattern to suit your preference (e.g., yy-MM-dd_HHmm).
  4. Click on “Save” to apply the configuration.

Now we can add the stage to our pipeline

 stage ("Upload Artifact") {
steps {
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: 'http',
nexusUrl: "${NEXUS_IP}:${NEXUS_PORT}",
groupId: 'QA',
version: "${env.BUILD_ID}-${env.BUILD_TIMESTAMP}",
repository: "${RELEASE_REPO}",
credentialsId: "${NEXUS_LOGIN}",
artifacts: [
[artifactId: 'vproapp',
classifier: '',
file: 'target/vprofile-v2.war',
type: 'war']
]
)
}
}

Save, commit and push to trigger the pipeline.

You can run a couple more times to see the effect of the Build Timestamp plugin.

If you’ve made it to this point, you deserve a pat on the back. Well Done!!!!!. We’re at the last and final stage of this project. This part involves creating a notification for you and your team using Slack. To achieve this, follow these steps;

  1. Slack Workspace Setup:
  • Open your web browser and search for “Slack Login.”
  • Sign in and click on “create a workspace.”
  • Give the team a name, e.g., Pipeline.
  • Provide your name and invite other team members via email if needed.
  • Name your project, e.g., CICD.

2. Install Slack App and Generate Token:

  • Search for “Slack apps” in Google.
  • Select the first tab and search for “jenkins ci.”
  • Click on “add to Slack” and choose the channel “cicd”
  • In step 3, copy the generated token and save it.
  • Scroll to the end and click on “save settings.”
  • Note the steps provided in Jenkins Slack App Directory

3. Configure Jenkins Integration:

  • Go to Jenkins and provide the Slack token.
  • In the “Manage Jenkins” section, go to “System Configuration.”
  • Scroll down to “Slack,” provide the workspace name, and give the token as a secret text.

4. Add Slack Notification Stage to Pipeline:

  • Now, let’s add the stage to our Jenkins pipeline. Modify your Jenkinsfile
def COLOR_MAP = [
'SUCCESS': 'good',
'FAILURE': 'danger',
]

pipeline {
agent any
tools {
maven "MAVEN3"
jdk "OracleJDK17"
}

environment {
SNAP_REPO = 'vprofile-snapshot'
NEXUS_USER = 'admin'
NEXUS_PASS = 'admin123'
RELEASE_REPO = 'vprofile-release'
CENTRAL_REPO = 'vpro-maven-central'
NEXUS_IP = '172.31.95.74'
NEXUS_PORT = '8081'
NEXUS_GRP_REPO = 'vpro-maven-group'
NEXUS_LOGIN = 'nexuslogin'
SONARSERVER = 'sonarserver'
SONARSCANNER = 'sonarscanner'
}

stages {
stage('Build'){
steps {
sh 'mvn -s settings.xml -DskipTests install'
}
post {
success {
echo 'Archiving'
archiveArtifacts artifacts: '**/*.war'
}
}

}

stage('Test') {
steps {
sh 'mvn -s settings.xml test'
}
}

stage('Checkstyle Analysis') {
steps {
sh 'mvn -s settings.xml checkstyle:checkstyle'
}
}

stage ('Sonar Analysis') {
environment {
scannerHome = tool "${SONARSCANNER}"
}
steps {
withSonarQubeEnv("${SONARSERVER}") {
sh '''${scannerHome}/bin/sonar-scanner -Dsonar.projectKey=vprofile \
-Dsonar.projectName=vprofile \
-Dsonar.projectVersion=1.0 \
-Dsonar.sources=src/ \
-Dsonar.java.binaries=target/test-classes/com/visualpathit/account/controllerTest/ \
-Dsonar.junit.reportsPath=target/surefire-reports/ \
-Dsonar.jacoco.reportsPath=target/jacoco.exec \
-Dsonar.java.checkstyle.reportPaths=target/checkstyle-result.xml'
''
}
}
}

stage ("Quality Gate") {
steps {
timeout(time:1, unit: 'HOURS') {
waitForQualityGate abortPipeline: true
}
}
}

stage ("Upload Artifact") {
steps {
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: 'http',
nexusUrl: "${NEXUS_IP}:${NEXUS_PORT}",
groupId: 'QA',
version: "${env.BUILD_ID}-${env.BUILD_TIMESTAMP}",
repository: "${RELEASE_REPO}",
credentialsId: "${NEXUS_LOGIN}",
artifacts: [
[artifactId: 'vproapp',
classifier: '',
file: 'target/vprofile-v2.war',
type: 'war']
]
)
}
}
}
post {
always{
echo 'Slack Notifications'
slackSend channel: '#cicd',
color: COLOR_MAP[currentBuild.currentResult],
message: "*${currentBuild.currentResult}:* Job ${env.JOB_NAME} build ${env.BUILD_NUMBER} \n More info at: ${env.BUILD_URL}"
}
}
}

This step elevates the professionalism of your CI pipeline, and with the seamless integration with Slack proving successful, we can now consider this project officially completed. Congratulations, and here’s to successful endeavors in DevOps Engineering!

Bình luận (0)

Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough

Bài viết liên quan

Learning English Everyday