Continuous Integration with Bitbucket Server and Jenkins

I have started several projects where I develop plugins for Bitbucket Server and Jenkins. They are independent of each other but I thought it would be nice to have a blog post about how they can work together and on how I prefer to do continuous integration. This is it! =)

What is the configuration that I apply?

  • Gitflow workflow.
  • Every commit, message and code, has to be reviewed before it can be merged.
  • Every commit has to have an issue in its message.
  • The size of the files that are put under version control cannot exceed 2000kb.
  • The committer must use valid name and email in all commits.
  • Changes can only be made with feature branches and merged with pull requests.
  • Pull requests cannot be merged unless it its guaranteed that the target branch will still build after merge.
  • Pull requests cannot be merged unless, at least, one other developer has reviewed it.
  • Static code analysis will be made on every pull request.

Why do I apply this configuration?

  • Git flow enables you to
    • Use plugins for managing releases, like JGit-Flow.
    • Reduce time spent on documentation. You just need to refer to some youtube-videos or websites.
    • Discuss any scenario on any public forum like Stackoverflow.
    • Let a configuration manager have total control of master and release-branches. While developers have total control of dev and feature-branches.
    • Some people skip dev and use master as developer branch. I keep dev because when developing tools around GIT, its convenient to have a reference to latest release, master, and latest snapshot, dev. And since branches in git are basically just a file with a hash I think its a small price to pay for keeping it nice and tidy.
  • You will know exactly what is included in your releases. The commits are reviewed, so you can trust that the message is true. Which means you can create your release notes by looking at the new commits in dev that are not yet merged to master (production). A special QA-jira is created to use for small fixes, like correcting toggling test case or formatting code.
  • You will make the code more maintainable and share knowledge among developers. When tracking down a bug, the commit messages you find will be clear and understandable. Also the code will be cleaner from the reviews. Duplicated utility classes, diverging patterns... and so on will be denied.
  • You will never have a failing build on a shared branch. Merge is only allowed, blocked by the Bitbucket Server, if it is guaranteed that target will still build after merge. Actually, if you have toggling test cases they can fail. But that should be found in code reviews.
  • Testers can pick a feature and try it out in a test environment before its merged to dev. By letting Jenkins perform the merge (without pushing), build the artifacts and deploy to an environment.
  • Your static code analysis will be honored. You will see dramatically reduced amount of warnings from static code analysis. The developers will not be able to ignore such warnings (often the case with Sonar) as they will automatically be converted into comments on the code in the pull request.
  • Your repository will not quickly increase in size. Remember that when you clone a Git repo you will download every version of everything. Its mostly a one time thing for a developer but something that a build server does several times a day. Once your repo has grown big its a bit of a pain getting rid of those large files.

And finally, how do I apply the configuration? With Jenkins, Bitbucket Server (some of this is also possible to do if you are using GitHub) and plugins! I created a small Docker Compose to help fiddle with this.

Bitbucket Server

This is the Git repo that I use. It adds some things that Git does not have:

  • Authentication.
  • Branch, repo and project permissions.
  • Pull request support.
  • Code review support.
  • Alot of plugins.

The plugins I will use adds support for:

You can think about Git as an open database. Anyone can change anything. Anyone can add commits to any branch, with any author/committer name/email. It is very dangerous to collaborate around a repo that is not protected with a service like Bitbucket Server.

Simple Bitbucket Server Commit Checker

This is one of my plugins. Its available for easy install from Atlassian Marketplace and is developed on Github.

The main reason why I developed this plugin was to allow custom rejection messages. The rejection messages also allows you to use variables so that you can reject a commit with a message saying exactly what the committer needs to do in order to fixup the commit. It also has a dry run mode where it only complains about the things that are not correct, but does not actually block the commit. It may be crucial to have such a feature if you introduce commit checks for 100+ committers.

Block committer emails not in Bitbucket Server

The rejection messages are very clear.

Email rejected

It uses Jira:s JQL to enable advanced and flexible validation of commit comments. It does not have to be an advanced query, simply adding issue = ${REGEXP} will validate that the Jiras exists.

JQL

I use it to block commits:

  • Contains files that are too big, larger then 2000kb.
  • Committer email or name does not match authenticated user in Bitbucket Server.
  • Message does not contain an issue. Jira or custom incident pattern. I create a special issue in jira, a QA-jira, that can be use for small fixes. A small fix might be correcting toggling test case or formatting code.

Pull Request Notifier for Bitbucket Server

This is one of my plugins. Its available for easy install from Atlassian Marketplace and is developed on Github.

It invokes a URL when a pull request event happens in Bitbucket Server. The URL is completely customizable and supports variables so that you can notify any system with the information it needs on the format it needs it.

Pull Request Notifier for Bitbucket Server URL config

The main reason why I developed this plugin was to allow perfect verification of pull requests in Jenkins. But it is written in a way so that it is in no way limited to Jenkins. It basically just interacts with HTTP and can be used for many other purposes. I know people use it for posting updates regarding pull requests in Slack channels.

It enables you to guarantee that pull requests cannot be merged unless target branch will still build after the merge. If one of several pull requests to dev is merged, the plugin can re-trigger all other pull requests to verify them with the new commit that is now dev.

It adds support for custom buttons on pull request view. These buttons are mapped to a notifications (a URL being invoked). This means you can have a button labeled "Deploy to test env 1" and when it is pressed you trigger a job in Jenkins. The job is served with the feature branch of the pull request, builds the artifact and deploys it to that environment.

Pull Request Notifier for Bitbucket Server Button Config

And in the pull request view you will see that button to the right, when clicking the dots.

Pull Request Notifier for Bitbucket Server Button In PR view

The button will only be made visible if there is a configured notification that will actually trigger on the button being pressed. So make sure you add that also.

Pull Request Notifier for Bitucket Server Triggers

Settings Synchronizer for Bitbucket Server

This is one of my plugins. Its available for easy install from Atlassian Marketplace and is developed on Github.

It is a bit of a pain to configure plugins for a 100, or even just a couple, of repositories. This plugin lets you synchronize plugin settings among your repositories.

Settings Synchronizer for Bitbucket Server

Jenkins

The build server that I use. Some say its just a glorified cron job. And yes thats pretty much it. The good thing about it is all the plugins. I dont think I would ever use it if it was not for the plugins.

When I verify the pull requests I do it with a simple shell script build step.

  • From Pull Request Notifier for Bitbucket Server I pass the ${EVERYTHING_URL}.
  • I check the job as parameterized and add the variables, used below, ass parameters.
  • I check delay and set it to 0 seconds.
  • I check allow parallel jobs.

The script is something like this.

git clone $PULL_REQUEST_TO_HTTP_CLONE_URL  
cd *  
git reset --hard $PULL_REQUEST_TO_HASH  
git status  
git remote add from $PULL_REQUEST_FROM_HTTP_CLONE_URL  
git fetch --all  
git merge $PULL_REQUEST_FROM_HASH  
git --no-pager log --max-count=10 --graph --abbrev-commit

#compile command here ...

Violation Comments to Bitbucket Server Plugin

This is one of my Jenkins plugins. It is available in Jenkins update sites and is developed on Github. There is also a Jenkins plugin for Github if that is what you are using.

My opinion is that projects often put to much trust in that developers themselves will adhere to rules specified by static code analysis tools. They often trust that developers will have their IDE setup correctly to report problems. They also trust that developers will browse to SonarQube, every now and then, and find problems to fix. It is my strongest opinion that this never works. Some developers are really enthusiastic about it in the beginning but soon forgets to check for problems. Some never even cares in the first place. Commenting the pull requests with the problems found, makes them hard to ignore.

When a pull request is verified, part of the verification is static code analysis. This plugin finds report files generated from that analysis and uses them to comment the pull request in Bitbucket Server.

Violation Comments to Bitbucket Server

The post build action may look something like this.

Violation Comments to Bitbucket Server Post Build Action

Git Changelog Plugin

This is one of my Jenkins plugins. It is available in Jenkins update sites and is developed on Github.

There may be several commits in the feature branch that is the source of the pull request. It may be an integration branch where developers has been working for weeks or even months. Then its very nice get a more organized view of what the feature branch actually contains.

Git Changelog Jenkins Plugin Configuration

This plugin is configured with a template and then creates a changelog where the template is rendered with the content of the feature branch.

Git Changelog Jenkins Plugin Template Configuration

It may look something like this if you chose to publish it on Jenkins job summary page. I used a Github repo here in the example because I dont have access to a Jira installation, but it works just the same with Jira! =)

Git Changelog Jenkins Summary

You can also use this plugin to create release notes, just select dev as source branch and master as target branch. If you have a Jenkins job for dev then that is where to put that. It includes integration with MediaWiki so that releasenotes can be posted there. You can also chose to create a file where you are totally free to create a formatted HTML with CSS, or just plain text, the way you like it.

Stash Notifier Plugin

It is available in Jenkins update sites. It adds a post build step in Jenkns.

Post Build Step in Jenkins

It also reveals build status on Pull request view in Bitbucket Server.

Build status in Bitbucket Server

Conclusions

Hope you found something useful here. Pull requests and suggested features are always welcome. Please dont email me directly but instead try to file issues on GitHub!