github twitter linkedin
Git Feature Branching With Jenkins and SonarQube
2015-05-14

In this article I’m going to explain how to work with git feature branches and get CI with Jenkins and source code metrics with SonarQube.

First, open your Jenkins Update center and install the Multi-Branch Project Plugin, the SonarQube Plugin and the Git plugin.

Now create a new job, choose the “Freestyle multi-branch project” type. The setting “Sync Branches Schedule” determines how often the plugin should look for added/removed feature branches. Choose git as VCS and enter the path to the repository. Under build, configure your build. I’ve used maven for a quick demo project. Save the project.

After some time (5 minutes per default), the Multi-Branch plugin detects your master branch and creates a sub-project for it. For every found branch the plugin creates such a sub-project, which has the same settings as the parent project, it differs only in the branch to build.

Sub-projects in Jenkins

Now we have a Jenkins job for every branch in our project. The color of the marble of the parent project is the color of the worst branch (if one branch is red and all others are blue, the parent project marble will be red). Let’s integrate SonarQube.

In your Jenkins system settings configure a SonarQube installation. Open up the configuration of your project (the parent project, not one of the sub-projects) and configure SonarQube as a “Post-build Action”. Click on “Advanced” and enter $GIT_BRANCH in the “Branch” field. This will make sure that SonarQube creates a sub-project for every feature-branch.

SonarQube configuration

Schedule a build, grab a Club-Mate and open up your SonarQube Web-UI. For every branch in your project which has been built by Jenkins, a new SonarQube project has been created. Great, isn’t it?

Sub-projects in SonarQube

There’s only one caveat: If you merge a feature branch into master and delete the branch on the remote, the job in Jenkins disappears. But the project in SonarQube will stay there forever until you manually delete it. But don’t worry, I’ve got you covered. We leverage the power of git commit hooks to get notified when a remote branch has been deleted and use the SonarQube API to delete the sub-project in SonarQube.

Open up your git repository on the remote. It looks like this:

moe@Moe-PC ~/tmp/repo $ ls -la
insgesamt 40
drwxr-xr-x  7 moe moe 4096 Apr 30 18:29 .
drwxr-xr-x  5 moe moe 4096 Apr 30 18:29 ..
drwxr-xr-x  2 moe moe 4096 Apr 30 18:29 branches
-rw-r--r--  1 moe moe   66 Apr 30 18:29 config
-rw-r--r--  1 moe moe   73 Apr 30 18:29 description
-rw-r--r--  1 moe moe   23 Apr 30 18:29 HEAD
drwxr-xr-x  2 moe moe 4096 Apr 30 18:29 hooks
drwxr-xr-x  2 moe moe 4096 Apr 30 18:29 info
drwxr-xr-x 19 moe moe 4096 Apr 30 19:47 objects
drwxr-xr-x  4 moe moe 4096 Apr 30 18:29 refs

See the folder hooks? That’s where the magic happens. Open that directory and the place the following script as a file called update. Don’t forget to mark it as executable (chmod +x update).

#!/bin/bash
#

# SonarQube settings
SONARQUBE_URL="http://localhost:9000"
SONARQUBE_USER="admin"
SONARQUBE_PASSWORD="admin"
SONARQUBE_PROJECT_ID="test:test"

# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"

# --- Safety check
if [ -z "$GIT_DIR" ]; then
	echo "Don't run this script from the command line." >&2
	echo " (if you want, you could supply GIT_DIR then run" >&2
	echo "  $0 <ref> <oldrev> <newrev>)" >&2
	exit 1
fi

if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
	echo "usage: $0 <ref> <oldrev> <newrev>" >&2
	exit 1
fi

# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
	newrev_type=delete
else
	newrev_type=$(git cat-file -t $newrev)
fi

function delete_from_sonar {
	branch=$(echo $1 |cut -d"/" -f3)

	curl -X POST -u $SONARQUBE_USER:$SONARQUBE_PASSWORD $SONARQUBE_URL/api/projects/destroy?id=$SONARQUBE_PROJECT_ID:origin/$branch 1>/dev/null

	echo "Deleted $branch from SonarQube"
}

case "$refname","$newrev_type" in
	refs/heads/*,delete)
		delete_from_sonar $refname
		;;
esac

# --- Finished
exit 0

In this script you need to configure the four variables on top. SONARQUBE_URL specifies the url to your SonarQube (don’t include the trailing slash). SONARQUBE_USER and SONARQUBE_PASSWORD are the credentials for a user which has the right to delete the projects. SONARQUBE_PROJECT_ID is the id in sonar, which you can find on the SonarQube dashboard.

Project id on the SonarQube dashboard

In this case, the variable SONARQUBE_PROJECT_ID has to be set to test:test. The part after the last colon is the branch and can be omitted.

Now every time you delete a remote branch (with git push origin --delete <branch>), the project in SonarQube is deleted, too.

Enjoy your branching!


Back to posts