Git branching strategiesGit branching strategies are policies on how to use git for development. This allows you to establish a common work-flow that all team members can use and help make updates easier.
There are a number of branching strategies available and they offer various pros and cons depending on your releasing and development methodologies. For our model we have implemented a slight variation on the git flow model. The main changes from this model that we have implemented are:
- master is used as the current development branch.
- production is used as the release branch.
- All changes to master and production must be pushed to Gitlab.
- All changes to master and production must be tested via Jenkins.
- All changes to master and production must be code reviewed.
Some of the other models such as github flow are more aligned towards software which follows a continuous deployment model where all changes should be pushed to production after testing instead of having to release software to customers.
Other toolsThe tools we use to help with our work flow include Gitlab for the central git server and Jenkins for continuous integration.
GitlabGitlab is git repository management tool, which includes user management, code review, merge requests, wiki and more. It could be considered similar to github and is quickly catching up on features and usability. However, the main area where it is ahead of github and what caused me to choose it was that it has an open source community edition which allows for free, easy to install, onsite installations.
JenkinsJeninks is a automation server that supports continuous integration and deployment. It is easily extensible and has many plugins to support most common build and integration tools. This allows it to easily integrate with build and source control tools to receive notifications and automatically update, build and test software.
Build SystemAs previously mentioned this post is about building and testing a software project which is C++ based and uses CMake as the build tool. The core platforms to build for are RedHat based systems including RedHat 5, 6, and 7.
ConfigurationIn this section I will cover configuration of the various servers. First, I will look at the Gitlab configuration and how the branches and hooks are configured. Secondly, I will cover the Jeninks configuration which builds and tests the software.
GitlabThe installation of Gitlab is via the Gitlab CE omnibus edition Debian package on an Ubuntu server. This is standard and covered on here.
User accounts, groups and the repository are created. In this example the group is example-group and the project is example-project.
Protected BranchesTwo branches master and production are created an set to protected. As described in the Gitlab UI, protect branched are designed to:
- prevent pushed from everybody except masters
- prevent anyone from force pushing to the branch
- prevent anyone from deleting the branch
|Gitlab Protected Branches|
WebhookWebhooks are configured to sent a HTTP request to the URL http://<jenkins-host>/gitlab/build_now for push events. As described later, this will trigger the Gitlab plugin in Jenkins.
Finally, deploy keys for the Jenkins users are configured on the repository to allow the jenkins user to clone the code.
JenkinsFor this example, Jenkins v1.607 is installed on one server. All builds are performed on the slave nodes buster, earth, and jupiter, where each node has a different version of RedHat installed.
The following are the main plugins used for this example:
- Git Plugin - Allows you to use git as a SCM with Jenkins.
- Gitlab Hook Plugin - Allows Jenkins to receive Gitlab web hooks and trigger builds.
Note: There is a Gitlab Merge Request Builder Plugin but I have not had a chance to configure it yet.
Gitlab Hook Plugin
|Gitlab Web Hook configuration|
Enable "automatic project creation" and set the project master branch to "master".
Combined with the Gitlab webhook configuration above, this will cause Jenkins to create a new project for every branch that is pushed to Gitlab and have it use the project associated with the master branch as a template.
This allows Jenkins to automatically build and test every commit on every branch that is pushed to Gitlab. By having every branch tested before merging we ensure that all changes are working as expected and that they should be safe to merge into the one of the core branches.
Git PluginConfiguration of the git plugin is from the project configuration page as shown below:
|Git Plugin project configuration|
The option to "Clean before checkout" will run a git clean on the project repository to remove any temporary build files from any previous runs of the job.
Job configurationThe configuration of the build job and steps is fairly standard multi-configuration project.
A configuration matrix is configured to run the job on each of the relevant build server slaves.
|Build Slave Configuration Matrix|
I then created an "Execute Shell" action which will call bash scripts that are in a jenkins folder as part of the repository. This allows you to the actual build commands to be under source control as part of the repository instead of in the Jenkins database. It can also allow slight variations of the build per branch.
|Jenkins Execute Shell Build Step|
build_step.sh runs CMake and make to compile the software.
#!/bin/bash -ex mkdir build cd build cmake .. make
test_step.sh runs CTest to make sure all unit tests pass.
#!/bin/bash -ex cd build ctest -Vrpm_step.sh uses CPack to create both an RPM and .tar.gz package.
#!/bin/bash -ex cd build make package
Finally after the build has completed one of two options can happens:
- On success the .rpm and .tar.gz build artifacts are archived for use by other jobs.
- On failure an email is sent to the relevant developer group
|Post Build Actions|
Branch JobsAll branches will by default create a new job that is a clone of the above master job. These jobs will be called "example-project_<branch name>" and will build the software on every push to Gitlab.
This is also true for the the production branch where a branch "example-project_production" is create. After creation it is possible to make changes to these jobs to add additional build steps required for customer releasable software, for example, you could add a test to make sure that release notes are available or you can SSH the rpm file to a central release server for installation at customer sites.
Merge RequestsAs mentioned in the git flow description we have added the step that all branches must be pushed to Gitlab.
The advantage to this is that it requires a merge request to be issued. These merge requests must be approved by another developer to ensure that:
- They meet any coding standards.
- Changes are of sufficient quality.
- Changes are checked by at least 2 developers to help spread knowledge.