Customize environments for different branches of a Continuous Integration project

- By Abhijit Kini

BACK TO BLOG HOME

There have been several requests on our support forum on how to customize environments to specific branches while running Continuous Integration (CI) builds for a repository that has multiple branches. In this tutorial, I'll go over a common scenario and review the multiple ways we can configure branch-specific actions during the CI build. 

The scenario I use for this tutorial is, to pull a Docker image in the CI process and upon completion, use different tags for the branches when pushing the Docker image to Docker Hub. The Docker tags should be customized to the specific branch where the CI was processed and should include the build number. The final results of successful CI process tagging different branches looks as shown.

Customized tags for Docker images after successful Continuous Integration

Prerequisite

To maximize your understanding of this tutorial, ensure you have:

Look out for 'ACTION' titles in this tutorial, where you'll have to make changes on your fork.

Ways to customize the environment for different branches

There are many ways one can accomplish the scenario of customizing the tags for a Docker image, per branch, before pushing it to a Docker Registry. I'll go over three of them:

  1. Modifying the shippable.yml file for each branch
  2. Keeping the shippable.yml file consistent for both branches
  3. Using a script

Before we jump into each of the ways, I would like to call out the use of 'BRANCH', a standard environment variable, available for use within the build. This env variable, gives you the current branch being built and can be used to trigger various actions as shown in the scenarios.

Let's get started with the first scenario.

Modifying the shippable.ymlfile for each branch

When the logic for each branch is different, the shippable.yml file for each branch can be modified to have different results. For example, I would like to tag the 'Master' branch with the branch name and the build number after every CI run. On the other hand, I want to tag the 'Tutorial' branch with the name of the repository and the build number after every CI run.

ACTION: For this scenario, do the following on your fork of the sample application:

  • Update the shippable.yml file for the 'Master' branch using the sample below
  • Add a shippable.yml file to the 'Tutorial' branch using the 'Tutorial' sample below
  • Commit the changes to both the branches which triggers two builds on the Shippable platform
# yml file for the Master Branch
# Language settings language: node_js build: ci: - docker pull abhijitkini/sample_node_eb_docker:latest post_ci: - docker tag -f abhijitkini/sample_node_eb_docker:latest abhijitkini/sample_node_eb_docker:$BRANCH.$BUILD_NUMBER - docker push abhijitkini/sample_node_eb_docker:$BRANCH.$BUILD_NUMBER integrations: hub: - integrationName: "Docker Hub" type: docker branches: only: - master
# yml file for the Tutorial Branch
# Language settings
language: node_js build: ci: - docker pull abhijitkini/sample_node_eb_docker:latest post_ci: - docker tag -f abhijitkini/sample_node_eb_docker:latest abhijitkini/sample_node_eb_docker:$REPO_NAME.$BUILD_NUMBER - docker push abhijitkini/sample_node_eb_docker:$REPO_NAME.$BUILD_NUMBER integrations: hub: - integrationName: "Docker Hub" type: docker branches: only: - tutorial

 I leverage the standard environment variables to achieve my objective for each branch. With these shippable.yml files in place, the output of the CI run for each branch on the Shippable platform  is shown below:

Continuous Integration output with Docker tags for Tutorial branch

Continuous Integration output with Docker tags for Master branch

With the successful runs on both the branches, the output is:

  • 'Tutorial' branch: Docker image abhijitkini/sample_node_eb_docker hosted on Docker Hub is tagged with BRANCH = sample_node_eb_docker and BUILD NUMBER = 21
  • 'Master' branch: Docker image abhijitkini/sample_node_eb_docker is tagged with BRANCH = Master and BUILD NUMBER = 22

Keep the shippable.ymlfile consistent for both branches

To keep the shippable.yml file consistent across all branches, I'll use a custom environment variable to set an env_name value based on a logic I want to implement. For example, I would like to tag the 'Master' branch with a customized branch name and tag the 'Tutorial' branch with another customized branch name after every CI run.

ACTION: For this scenario, do the following on your fork of the sample application:

  • Update the shippable.yml file for both the 'Master' and 'Tutorial' branches using the sample below
  • Commit the changes to both the branches which triggers two builds on the Shippable platform
# yml file for both Master and Tutorial Branch
# Language settings language: node_js build: ci: - docker pull abhijitkini/sample_node_eb_docker:latest post_ci: - if [ "$BRANCH" == "master" ]; then TAG="master_env"; fi - if [ "$BRANCH" == "tutorial" ]; then TAG="tutorial_env"; fi - docker tag -f abhijitkini/sample_node_eb_docker:latest abhijitkini/sample_node_eb_docker:$TAG - docker push abhijitkini/sample_node_eb_docker:$TAG integrations: hub: - integrationName: "Docker Hub" type: docker

The shippable.yml files for both branches are consistent and same. The output of the CI run for both branches are similar. The 'Master' branch output is shown below:

Continuous Integration output with tags to the Docker image per branch

Based on the successful run on both branches, the output is:

  • 'Master' branch: Docker image abhijitkini/sample_node_eb_docker hosted on Docker Hub is tagged as 'master_env'
  • 'Tutorial' branch: Docker image abhijitkini/sample_node_eb_docker will have the tag 'tutorial_env'.

Using a script

For scenarios where several commands need to be executed and are unique to each branch, then the logic can be built into a script and then used in the  ci section of the shippable.yml file. In this example, I would like to tag only the 'Tutorial' branch with a string 'script' using a deployment script, after every CI run for this branch.

ACTION: For this scenario, do the following on your fork of the sample application:

  • Update the shippable.yml file for both the 'Master' and 'Tutorial' branches using the sample below
  • Commit the changes to both the branches which triggers two builds on the Shippable platform
# yml file for both Master and Tutorial Branches
# Language settings language: node_js build: ci: - docker pull abhijitkini/sample_node_eb_docker:latest post_ci: - if [ "$BRANCH" == "tutorial" ]; then ./deployment_script.sh; fi integrations: hub: - integrationName: "Docker Hub" type: docker
branches:
only:
- tutorial

I have a simple script in the file deployment_script.sh that tags the Docker image with the string 'script' and pushes it to Docker Hub. You can use scripts with a logic to include several commands, as needed.

#!/bin/bash
docker tag -f abhijitkini/sample_node_eb_docker:latest abhijitkini/sample_node_eb_docker:script
docker push abhijitkini/sample_node_eb_docker:script

In this example, shippable.yml files for both branches are consistent and same. The output of the CI run for both branches are similar. The 'Tutorial' branch output is shown below:

Continuous Integration output tagging a Docker image based on a script

Based on the successful run on both branches, the output is:

  • 'Tutorial' branch: Docker image abhijitkini/sample_node_eb_docker hosted on Docker Hub is tagged as 'script'
  • 'Master' branch: No tag is set on the Docker image

Review tags in Docker Hub

We've gone through three scenarios where the outputs were Docker images tagged in unique ways for each branch after a successful CI run. Let's take a look at those tagged images on Docker Hub.

ACTION:

  • Log in to your Docker Hub account
  • Access your sample_node_eb_docker repository
  • Review the 'Tags' tab

tutnode125_dockerhub.png

 

This tutorial gives you simple examples of customizing environments for different branches of your repository while running Continuous Integration. Per your requirements, use these examples and expand on them to include more complex logic to achieve your objectives.

Questions or feedback, use the 'Comments' section below. Alternatively, you can also contact us through support.


Try Shippable 

Topics: Docker, continuous integration (CI), how-to, tutorial, tips, Public Repository, private repository