Deploying a Phoenix (Elixir) App to Gigalixir using Travis CI

Elixir

TLDR; If you use Travis CI and want to deploy to Gigalixir, start with this gist.


I just started using Gigalixir to host a web application I’m writing in Elixir. I already use Travis CI to run tests via GitHub, so one of the things I wanted to investigate was how to deploy my application to Gigalixir from Travis after tests pass.

Firstly, let me start off by saying that the documentation for Gigalixir is great, especially considering it is (if I assume correctly) a one-man operation run by Jesse Shieh, the type of developer who took the time to personally assist me in getting a manual deploy set up when he noticed the questions I posted in the Elixir Slack Community.

So I dove right in. There was a section on setting up continuous integration. Cool, I just needed to add some environment variables and a line in my .travis.yml to configure a git remote for Gigalixir. Then just another line to test and push/deploy. Great. I committed my changes (to master), pushed to GitHub, and went to watch the build and await satisfaction. I was pleased to find that the build succeeded and deployed just as expected!

Exited to get to work, I quickly made a new branch locally. I pushed the branch up to GitHub, and went to watch Travis do its thing. Travis built. Travis ran tests. The tests passed. THE APPLICATION DEPLOYED?! That would’ve been a nightmare if I had actually made changes!

I checked the docs again. Oh. It turned out the docs was enough to get me started, but it certainly needed some customizing unless I wanted Travis to deploy after builds for every branch and pull request. So I exchanged all the script section in my .travis.yml for the following, and got to writing a small deploy script:

script:
- mix test && ./deploy.sh

So… what I needed in deploy.sh to do now was: set up the gigalixir remote using the environment variables I added to Travis, figure out if the branch that just built was master, and deploy the branch if it was. Simple. Here’s something like what I tried:

#!/usr/bin/env bash
git remote add gigalixir https://$GIGALIXIR_EMAIL:$GIGALIXIR_API_KEY@git.gigalixir.com/$GIGALIXIR_APP_NAME.git
if [ "$TRAVIS_BRANCH" == "master" ]; then
echo "Pushing HEAD to master branch on Gigalixir."
git push gigalixir HEAD:master --verbose
echo "Deploy completed."
fi
echo "Exiting."

I knew $TRAVIS_BRANCH was available from looking at the docs, of course. I pushed the changes on the new branch to remote and watched Travis build. Travis ran tests. The tests passed. The application did not deploy! But I also knew that Travis would build for all pull requests, so there was one more thing to check.

I opened a pull request on GitHub from the new branch into master. I watched the build. Travis ran tests. The tests passed. THE APPLICATION DEPLOYED?? So I consulted Google: “travis pull request current branch name”. The first link made it obvious; someone has definitely run into this before. I read the post, then made changes to my script.

#!/usr/bin/env bash
git remote add gigalixir https://$GIGALIXIR_EMAIL:$GIGALIXIR_API_KEY@git.gigalixir.com/$GIGALIXIR_APP_NAME.git
BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR"
echo "------------------------------------"
echo "BRANCH=$BRANCH"
if [ "$BRANCH" == "master" ]; then
echo "Pushing HEAD to master branch on Gigalixir."
git push gigalixir HEAD:master --verbose
echo "Deploy completed."
fi
echo "Exiting."

I committed the changes. I pushed them remote to update the pull request. I watched Travis handle pull request. Travis built. Travis ran tests. The tests passed. The application didn’t deploy. But to truly be fixed would mean a deploy after merging the pull request; so I did, and watched Travis handle master yet again. Travis built and tested… and deployed!

Deploys are tricky, and I chose to use Gigalixir for hosting my application so that I could get the Heroku-like ease-of-use that it provides, while being able to still learn and use features of Elixir that make it special (like ETS and hot upgrades). With a little time (and a little help), I was able to set up a simple continuous integration pipeline that deploys to my new host!