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.
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.
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?
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.
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!