Deploying git tags on Nanobox

I’ve been using Nanobox for months now on my side projects, it is an amazing tool for dev(s)/teams that are solo or want to avoid devops work. One item that I miss from my devops days, was the ability to deploy based on a git tag. Being able to checkout the code that currently lives on production, at any time, saves a lot of headaches when it hits the fan.

Using a git tag for deployment

There are multiple steps that need to be executed to deploy a git tag:

  • Save the current branch name, not required, but a nice touch
  • Checkout the git tag into a detached state
  • Deploy via nanobox deploy -m '<message>'
  • Checkout the original branch

Obtaining the current branch

Using git branch will not have the desired results, as it lists all local branches. We need to only grab the starred item, and then trim off the star and spaces. The resulting string can be interpolated into a git checkout command for later execution.

initialBranch=`git branch | grep \* | cut -d ' ' -f2`
checkoutInitialBranch="git checkout $initialBranch"

Checking out the git tag

Based on how Nanobox deploys, we need the current working directory to mirror the git tag we wish to deploy. Also we should confirm with the user that they do want to deploy that tag.

if [[ $1 = "" ]] ; then
  printf "Missing tag name to deploy!\n"
  printf "Usage: ./prod_deploy.sh <tag_name>\n" 
  exit
fi

# Confirm with the user that this is indeed the tag to deploy.
printf "Tag to deploy: [$1]\n"
read -p "Are you sure you wish to deploy (y/n)? " answer

shopt -s nocasematch # case insentitive matching may save you one day
if [[ $answer =~ ^(n|no)$ ]] ; then
  printf "\nEject eject eject!!\n"
  exit
fi

Using shopt allows case insensitive matching on the input from the user. Confirming the deployment will protect against accidentally deploying the wrong tag.

Now that the safety net has been cleared, lets checkout some code. $1 holds the git tag we wish to deploy, as it was passed in via a command line argument.

# Checkout tag
checkoutCommand="git checkout $1"
if eval $checkoutCommand; then
  # checkout was successful
  printf "Tag checked out, starting deploy.\n"
  ...
else
  printf "$checkoutCommand returned a non-successful status code. Exiting.\n"
  eval $checkoutInitialBranch
  exit
fi

Using eval within the if statement allows us to check the return code, and fail if necessary.

Deploy using Nanobox deploy

With the current working directory at the correct state, it’s time to deploy. Nanobox allows you to add a deploy message to your deployment, which will be shown in your dashboard. This helps with finding out the current tag deployed, and selecting the proper deployment for rolling back.

  nanoboxDeploy="nanobox deploy -m 'Deployment of git tag: [$1]'"
  if eval $nanoboxDeploy; then
    printf "Deploy sucessful, monitor status from your dashboard!\n"
  else
    printf "Deploy failed.\n"
  fi
  eval $checkoutInitialBranch

Once the deploy is completed, you can head over to your dashboard and view your deployment status. The information on what tag was deployed is very helpful.

Deployment History

Checkout the original branch

To be polite, we should checkout the branch that user was on before the deploy. The command to execute is $checkoutInitialBranch and you will see it in the code above.

Entire bash script

I don’t use bash often, and those who do can suggest tweaks. However this works and is easy to follow for those who barely know bash, which was one of my goals. If you have any comments/suggestions please send me a message or tag me on Twitter, you will find a link to my profile on the left side of the page.

Gitlab Snippet

#!/bin/bash

printf "\n"

if [[ $1 = "" ]] ; then
  printf "Missing tag name to deploy!\n"
  printf "Usage: ./prod_deploy.sh <tag_name>\n" 
  exit
fi

# Save the branch name of the branch we were on before deploy. This enables
# us to be nice and checkout that branch post deploy
initialBranch=`git branch | grep \* | cut -d ' ' -f2`
checkoutInitialBranch="git checkout $initialBranch"

# Confirm with the user that this is indeed the tag to deploy.
printf "Tag to deploy: [$1]\n"
read -p "Are you sure you wish to deploy (y/n)? " answer

shopt -s nocasematch # case insentitive matching may save you one day
if [[ $answer =~ ^(n|no)$ ]] ; then
  printf "\nEject eject eject!!\n"
  exit
fi

# Checkout tag
checkoutCommand="git checkout $1"
if eval $checkoutCommand; then
  # checkout was successful
  printf "Tag checked out, starting deploy.\n"
  nanoboxDeploy="nanobox deploy -m 'Deployment of git tag: [$1]'"
  if eval $nanoboxDeploy; then
    printf "Deploy sucessful, monitor status from your dashboard!\n"
  else
    printf "Deploy failed.\n"
  fi
  eval $checkoutInitialBranch
else
  printf "$checkoutCommand returned a non-successful status code. Exiting.\n"
  eval $checkoutInitialBranch
  exit
fi