Jenkins In Detached HEAD

When you do a checkout scm in a Jenkinsfile, the Jenkins Git plugin does a checkout with a detached HEAD reference by default. The consequence of this is, that when you make changes after a checkout scm and commit them to the remote repo (from Jenkins), these changes DO NOT belong to any branch. This means that this commit and its ancestors are not bound to any specific branch. One useful use case of this is, when you want to create a release where you only change the version number (e.g. in the pom.xml) with a commit, and this commit then shouldn’t be part of e.g. the master branch. Here an example Jenkinsfile which deals with this:


def projectName = "my-first-project"
def teamEmail = "me@me.com"
def isMaster = (env.BRANCH_NAME == 'master')

node {
    def mvnHome = tool 'Maven 3.3.3'
    jdk = tool name: 'Java 1.8'
    env.JAVA_HOME = "${jdk}"

    stage('Checkout') {
    	// Checkout in detached HEAD to latest commit from master
        checkout scm
    }

    withNotification {
        version = calculateVersion(isMaster)
        tag = "v${version}"
        echo "Branch name:  ${env.BRANCH_NAME}"
        echo "Build number: ${env.BUILD_NUMBER}"
        echo "Version:      ${version}"
        echo "Tag:          ${tag}"

        if (isMaster) {
            // Change the version tag in the projects pom.xml
            sh "${mvnHome}/bin/mvn versions:set -DnewVersion=${version}"
            // Commit the changed pom.xml to the detached HEAD commit tree
            sh "git commit -a -m'Release version ${version}'"
        }

        stage('Build') {
            mvnWithSurefireResults(mvnHome, "clean package")
        }

        parallel 'Sonar analysis': {
            stage('Sonar') {
                sh "${mvnHome}/bin/mvn -B sonar:sonar -Dsonar.branch=${env.BRANCH_NAME}"
            }
        }, 'Dependency analysis': {
            stage('Dependencies') {
                sh "${mvnHome}/bin/mvn -B -Pdependency-analysis verify -DskipTests=true"
            }
        }

        if (isMaster) {
            stage('Release') {
                /*
                Create a tag with metadata and message, and add the
                tag to our new commit where the detached HEAD is
                pointing to.
                */
                sh "git tag -a -m 'Version ${version}' ${tag} HEAD"
                sh "git push origin refs/tags/${tag}"

                def lines = [
                        "Job '${env.JOB_NAME}' (#${env.BUILD_NUMBER}) has released version ${version}.",
                        "Please go to ${env.BUILD_URL} and verify the tag ${env.BRANCH_NAME}."
                ]
                lines.each { echo it }

                emailext subject: "New ${projectName} release: ${version}",
                        body: lines.join("\n"),
                        to: teamEmail
            }

            stage('Deploy to Artifactory') {
                sh "${mvnHome}/bin/mvn -B deploy -DskipTests=true"
            }
        }
    }
}

}
 

That's it! Have fun and let me know if I have forgotten to mention something important.

Live, Laugh and Learn Cheers

© 2021 Simon Berner • Crafted with ❤️

v1.0.0