One of the pending tasks I faced until recently in my work was to find a proper way to configure Jenkins to receive notifications from pushes in GitHub and use those to trigger a merge between every modified branch and the master one.

Defining the scenario

When developing within a collaborative environment, there are multiple approaches to divide the work among different teams. The approach we use to build our framework is to create a branch per software component, plus a master one where all the others are merged into.

The merging task may be done manually or automatically. In the former case, one or more members of the team shall scan the chosen repository (e.g. GitHub) for changes, optionally validate them and integrate into the master branch. In the later case, no validation will take place as process will be automatically carried out through scripts. If done correctly (i.e. common structure is respected across branches and any change triggers a merge), an automatic merge should work smoothly.

You can find below the steps I followed to configure our environment so as to pull sources and automatically integrate them into master branch. There are probably other ways, using some existing plug-ins in Jenkins (maybe with Git Plug-in…).

The following steps assume the following:

  • Public repository available in GitHub
  • Jenkins used as CI tool
  • Organisation of the repository:
    • N branches, one per component (e.g. “component1“, “component2“, …)
    • One branch to merge them (e.g. “master“)
    • Similar or complementing structure across branches (i.e. preferably work in different directories and leave the root clean of files to modify)

Configuring Jenkins

First things first: Jenkins must be installed and configured.

Jenkins will automatically start after some time on the port 8080.

Another port can be chosen in the HTTP_PORT directive under the /etc/default/jenkins file. Also, if you use some DNS for easy access and you wish to use Nginx, you may create a new site file under /etc/nginx/sites-enabled/ and link it from /etc/nginx/sites-available/:

Creating tasks to detect and pull changes

To detect changes in any of the N branches from your project, you should create tasks to retrieve the latest sources upon any change:

Parameterize build

The task will receive a POST request from GitHub, which contains a parameter called “payload” and whose contents are a JSON structure. Thus the task must be parameterized, by using a text value with the name “payload“.

Parameterize the task with a text value

Parameterize the task with a text value

Fetching sources, checking branches out

Set up the repository details to pull the source code and check out to the specific branch (e.g. “component1“). You may also place the code in a specific directory, e.g. outside the Jenkins workspace.

Set up repository details and check out behaviour

Set up repository details and check out behaviour

Enable triggering builds remotely

Enable the checkbox to trigger building this task remotely (through the GitHub webhooks) and define an authentication token, such as “organisation-git-push-component1“. The resulting address will be something such as “http://<ci.subdomain.domain>/job/git-pull-component1/buildWithParameters?token=organisation-git-push-component1“.

Enable triggering builds remotely

Enable triggering builds remotely

Conditional step sources, checking branches out

In the conditional step, add scripting code that process the incoming payload.

Add conditional step to run and build other tasks

Add conditional step to run and build other tasks

This script processes the GitHub payload to fetch the name (“ref“) of the branch where some changes were pushed. Any other processing of the payload -such as obtaining the modified files, name and e-mail of the committer, commit hash, timestamp and so on- should be possible by following a similar procedure. Just bear in mind the structure of the GitHub payload, which you will be able to check by either looking at the GitHub example, enabling logging POST requests into your server of choice (e.g. Jenkins) or directly look into the “GitHub Webhooks” page, after any initial commit.

In this bash script, when 0 is returned, any dependant (downstream) task will take place. Otherwise (when 1 is returned), the task will end silently, with no errors.

Note that using the same script in the normal “Execute Shell” text area would result in an error, due to the triggered task attempting to process data from “$branch_name“, when different to the expected “$current_branch“.

Add downstream tasks

Finally, if some other task depends on this one (downstream task), it shall be defined as such.

Within “Conditional step (single)” > “Builder” > “Build triggers” > “Projects to build“, write the names of any merging task(s) to be performed after a successful build of this pull task.

Creating the hooks in GitHub

Finally, the whole thing must be activated. After due configuration, GitHub is expected to send a POST request against the URL you define, which will triggering the specific task.

Use the same authentication token used in “Enable triggering builds remotely“. The remote URL to add here is something like “http://<ci.subdomain.domain>/job/git-pull-component1/buildWithParameters?token=organisation-git-push-component1“. It is VERY important to define “Content Type” as “application/x-www-form-urlencoded“, as this enables GitHub to send the JSON payload as the value for the “payload” parameter defined in the first step.

Bonus: creating the merging task

A simple task will do here. Just remember to call it from the pull task(s) as a downstream task and then add a suitable script to merge branches within the “Build” > “Execute shell” text area.

The following script is what I use for automatically merging every branch (component) with changes into the master one. It follows a simple approach, as it assumes every change in any modified branch is “trustworthy” and can be passed down to the master branch:

Share on FacebookTweet about this on TwitterShare on Google+Share on RedditEmail this to someonePrint this page
Rate the usefulness:
(No Ratings Yet)