Deploying Every Branch

tl;dr

At Eager we deploy every branch of our app to a subdomain. It makes it easier to share, collaborate and test. We’re able to do it because we use Stout.


There’s a rule in engineering which says well-designed systems should accept 0, 1 or an infinite number of instances of any entity. In other words, if you’re designing a CMS, it makes sense to allow no headings, one heading per post, or any number of headings, but if you build your system to support exactly two headings or twenty headings something is wrong.

This was the nature of the issue which confronted our frontend deployment setup at Eager. We had a production site, a development site, and a staging site. Not 0, 1, or infinite, but precisely 3. Three was better than 1, but there was regular contention over what was on the development site at any given time. Tests were limited because with only one staging environment, multiple changes couldn’t be tested simultaneously. Long-living changes were hard to manage as merging them into dev would tie them up with the numerous small changes we make every day. Not having a change on dev meant it was not live on the internet making real-world testing diffucult.

The goal became to have every branch deployed onto the internet as it’s developed. To make it a reliable way of testing our app, it was critical that these deploys mirror the deployment and CDN infrastructure of our production app as much as is possible.

Fortunately, for other reasons we have our own open-source deploy tool at Eager. This project gave us a good excuse to integrate a new command into that tool, create. The create command creates an S3 bucket, a CloudFront CDN distribution, and an Amazon IAM account with rights to deploy to the bucket. It also updates the appropriate Route53 routing table to direct traffic to that new distribution.

After that was finished, all we needed to do was add something like this to our CircleCI configuration:

if [ "$CIRCLE_BRANCH" = "dep-*" ] then
  ./stout create --bucket "${CIRCLE_BRANCH}.eager.io" --key $AWS_KEY --secret "$AWS_SECRET" --no-user
  ./stout deploy --bucket "${CIRCLE_BRANCH}.eager.io" --key $AWS_KEY --secret "$AWS_SECRET"
  echo "The tests will fail on the first deploy, as it can take 20 minutes for the new distribution to be active"
  HOST="${CIRCLE_BRANCH}.eager.io" protractor tests/protractor.conf.js
fi

With that, every push to a branch beginning with dep- automatically gets its own branch at <branch name>.eager.io, and gets tested with our automated testing.

Security

It goes without saying that deploying anything out to the internet makes it public. As this is a frontend-only project, we as a rule never include secure credentials or information. Additionally, the requirement to prefix branch names with a specific token ensures that developers are aware of what becomes public when. Alternatively, you could use git branch descriptions, a special file, or an external database to define which branches should be shipped.

Like this post? Share it with your followers.

Sign up to get our next post delivered to your inbox.

Follow us to get our latest updates.