continuous_integration github labs

Coding while deploying with Git Deployment Directories

Two tenets of Pivotal are continuous integration and coding if you’re in front of a computer. These goals can conflict when you’ve just wrapped up a story and are about to push to a staging environment – while your final tests and deploy are running, you can’t modify your Git working tree. So you grab some coffee or check your email.

In the spirit of eliminating breaks enforced by devops, Dirk Kelly and Mik Freedman paired on a great way to run deploys in the background. In essence, you create a separate Git repository on your development machine, we’ll call it deployer, that has your original Git code repository as a remote. Your deploy scripts then run in background from the deployer directory while you happily code in your original directory.

If your deployment process is anything more than a push to GitHub, this saves a good amount of time. If your project involves more than 1 pair, continuous integration and automatic deployment of all Git branches can alleviate the pain of long deploys.

Setup

Below are the details of our setup. Assume that ~/code/client was our original Git repo and ~/code/client_deployer is our fancy new deployment repo. By keeping these scripts in your development repository and changing directories in the script, you can solve some chicken-egg problems by running the development version of the script against any of your environments.

Git Remote

In ~/code/client_deployer, add your original repository as a remote:

git remote add local ~/code/client/.git

Deploy Script

In the code below, the pushd, popd, and trap commands ensure that your working directory is always left untouched no matter how the script exits. First, we essentially discard all local changes and check out the master branch. We then run our specs and associated rake tasks. Because we include set -e, our deploy will abort if the specs do not pass (or any command exits with a nonzero exit code). Then we push up to GitHub and Heroku (using heroku-san).

#! /bin/bash

set -e trap “popd” EXIT

pushd ~/code/client_deployer
git fetch local git co master
git reset local/master --hard
git clean -f -d
rake db:test:prepare
rake
rake production:deploy
git push origin master

Wrap Up

Nothing presented above is particularly revolutionary. Nonetheless, using a second deployment directory is a great way to remain “in the zone” while you code. Deploying doesn’t have to involve a coffee break or a ping-pong match anymore – just run your deploy in a background terminal and check on it when you come to a good stopping point.