Dynamically Increment Application version in Jenkins Pipeline

In practice, we have the requirement to increase the application version dynamically with the build tools like Maven for Java. We can delegate this task to Jenkins as well.

Preparation

First, we need to create an SSH key in the Jenkins server.

jenkins@71449dc3b2f9:/$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/var/jenkins_home/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/jenkins_home/.ssh/id_rsa
Your public key has been saved in /var/jenkins_home/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:Xm/CmCmPn2S22c3sUljsA+vj0a+5JlsjuW6E+icDJPs jenkins@71449dc3b2f9

Find the public key with "cat ~/.ssh/id_rsa.pub" and the private key with "cat ~/.ssh/id_rsa".

Go to Gitlab, Preferences -> SSH Keys, and add the public key here. Then we go to Jenkins UI, "Manage Jenkins -> Credentials -> System -> Global credentials (unrestricted)", and add a new credential. We paste the private key here. Then save it.

Later in the Jenkinsfile we will use the Credential ID.

Setup Jenkins Job

We use the sample repository with the branch 'jenkins-jobs'.

In the stage 'incrementing app version', it reads the pom.xml file and generates the new image_name with the next version number. "image_name" is then used in the "build image" stage later.

In the stage "commit version update", it commits the changes back to Gitlab with the Jenkins Credential "jenkins-ssh-key" we created.

Here is the JenkinsFile.

def gv  


pipeline {  
   agent any  
   tools {  
       maven 'maven'  
   }  

   stages{  
      stage('increment version'){  
         steps {  
            script{  
               echo 'incrementing app version'  
               sh 'mvn build-helper:parse-version versions:set \  
-DnewVersion=\\\${parsedVersion.majorVersion}.\\\${parsedVersion.minorVersion}.\\\${parsedVersion.nextIncrementalVersion} \  
versions:commit'  
               def matcher = readFile('pom.xml') =~ '<version>(.+)</version>'  
               def version = matcher[0][1]  
//                 echo "version is $version"  
               env.IMAGE_NAME = "$version-$BUILD_NUMBER"  
            }  
         }  
      }  

      stage('commit version update'){  
           steps{  
              script{  
                 withCredentials([sshUserPrivateKey(credentialsId: 'jenkins-ssh-key', keyFileVariable: 'keyfile')]){  
                 // set some Git configuration, we can also set this in the Jenkins server  
                          sh 'git config --global user.email "jenkins@example.com"'  
                          sh 'git config --global user.name "jenkins"'  

                          sh 'git status'  
                          sh 'git branch'  
                          sh 'git config --list'  

                          sh "git remote set-url origin git@gitlab.com:stevenchen5211/java-maven-app.git"  
//                            sh "git push -u origin jenkins-jobs"  
                          sh 'git add .'  
                          sh "git remote -v"  
                          sh 'git commit -m "ci: version bump"'  

                                sh 'GIT_SSH_COMMAND="ssh -i $keyfile"'  
                          sh 'git push origin HEAD:jenkins-jobs' //need to specify the branch name here. Because  
                       }  
              }  
           }  
        }  


      stage("build app"){  
         steps{  
            script{  
               echo "building the application..."  
               sh 'mvn clean package'  
            }  
         }  
      }  

      stage("build image"){  
         steps{  
            script{  
               echo "building the docker image..."  
               withCredentials([usernamePassword(credentialsId: 'Dockerhub', passwordVariable:'PASS', usernameVariable:'USER')]){  
                  sh "docker build -t stevenchen521/demo-app:${IMAGE_NAME} ."  
                  sh "echo $PASS | docker login -u $USER --password-stdin "                  sh "docker push stevenchen521/demo-app:${IMAGE_NAME}"  
               }  
            }  
         }  
      }  

      stage("deploy"){  
         steps{  
            script{  
               echo "deploying the application..."  
            }  
         }  
      }  
   }  

}

Summary

In this post, we showed how to dynamically increase the application's version in Jenkins.

However, there is a potential problem. Once we activate the Webhook, changes to the git repository trigger the Jenkins job. This is a deadlock. To solve this we need to install another plugin called "Ignore Committer Strategy"..

Reference

Module 8 of DevOps Bootcamp