By Josh Adams of ElixirSips

I have an application up at http://elixirfriends.com. It’s a Phoenix-based Elixir webapp. Since Phoenix hit 1.0 this week, I thought it would be a good time to outline how you can set up Continuous Integration and Deployment of a Phoenix-based application using Semaphore. Let’s get started.

Project Details

So this project lives at on GitHub at knewter/elixir_friends. It’s a pretty standard Phoenix application, and it uses a React-based frontend to render the views after talking to the API to get the data. One particularly fun piece of it is the ImageTweetStreamer, which gets a stream of tweets matching a given search term, filters out those that don’t have images, and stores them in the database if they haven’t already been stored. Using one of Phoenix’s more interesting features, Channels, we broadcast any newly-stored tweets to the frontend for real-time addition to the page. We then run this as a supervised Task when our application starts.

Alright, so we have our application and you have a good feel for how it works now. Where does Semaphore come into play?

Continuous Integration

Well, I’ve been writing software for long enough that I’m now of the opinion that if you don’t have tests you haven’t really written anything. Consequently, I have a few tests to verify that my API works as expected. Here’s the controller test, which very basically confirms that my API returns posts in our system.

But what good are tests if you aren’t running them? I run my tests as I’m building my software, but I *also* know that if I don’t automate things I’m not likely to be as rigorous as I’d like. To avoid merging Pull Requests that break the tests, I’d like to automatically run the tests on any Pull Request. In the past I’ve used Jenkins for this sort of thing, but honestly running my own infrastructure for CI is a bit time-consuming, and I’m especially unlikely to set it up for open source projects. Semaphore provides a very simple means to set up CI for anything ranging from small open source projects to large private projects.

Setting up Semaphore for Continuous Integration

Adding a Project

Once you’ve logged into semaphore, there’s a link in your dashboard to add a new project.

Add a new project

Selecting Your Repository Host

Semaphore provides nice integration with various potential repository hosts. Our app is on GitHub, so we’ll pick that:

Select Repository Host

Choose Repository

Semaphore now connects to GitHub via OAuth to list your repositories, and you can just click on the repository you want to set up CI for:

Choose Repository

Select Branch

Your branches will be listed, and you can choose the branch you care about:

Select Branch

Select Account

Next, you choose your Semaphore Account. I only have one:

Select Account

Analysis

This is one of the coolest features of Semaphore. It will analyze the project to determine which kind of project it is.

Analysis

Review the Build Plan

Since Semaphore knows it’s an Elixir project, it has a very good default plan in place. You’re provided with a screen to make any changes to the build in case your project requires additional setup.

Review the Build Plan

First Build

Once you’ve OKed the Build Plan, your first build is kicked off immediately:

First Build

Our First Build Fails

Our first build fails…you can see in the browser why it failed:

Build Fails Due to DB Settings

Set Up Database Configuration

The problem was due to our database connection failing. Semaphore provides you with a username and password to interact with your database in two environment variables:

DATABASE_POSTGRESQL_USERNAME
DATABASE_POSTGRESQL_PASSWORD

We modify our test environment for the Phoenix application to use these environment variables if they’re present:

Setup DB in Phoenix

Successful Build

When we push that fix up, Semaphore immediately kicks off the new build. This time it passes, because we’re able to talk to the database successfully:

Build Success

Setting up Semaphore for Continuous Deployment

So now we’ll know when our builds fail, which is very good. As soon as I’ve got Continuous Integration set up on a project, though, I prefer to immediately add Continuous Deployment. I find that automating my deployment from the master branch is a great way to avoid getting into the situation where all of my deployments require manual intervention. If you always have to support automated deployment, then you’re going to write better software and be more careful about what makes it into the master branch. Semaphore provides extremely easy-to-use support for adding Continuous Deployment.

First off, I set up my app so that I could deploy it with Heroku. For most of my applications I don’t use Heroku, but I definitely prefer to deploy open source and community-focused apps to Heroku because it makes collaboration a lot easier since I don’t have to manually manage permissions to my servers. Once I set that up, I set out to use Semaphore for Continuous Deployment for the first time.

Set Up Deployment

If you visit the projects page in your dashboard, there’s a button to that says “Set Up Deployment.” Seems like what we want, so let’s click that.

Set Up Deployment

Choose Deployment Type

Next, we’re presented with a choice of deployment types that are supported out of the box. We have a Heroku application, so we’ll choose that.

Choose Deployment Type

Select Strategy

Now we’re prompted to choose our strategy. We can pick either Automatic or Manual, but our whole point is to have Continuous Deployment so we choose Automatic.

Select Strategy

Choose Branch

Now we can pick the branch we want to deploy on success. We pick master, which happens to be our only branch at the moment anyway.

Choose Branch

Paste API Key

Since we’re deploying to Heroku, we’re not prompted for our Heroku API Key. There’s a handy link that takes you right where you need to go to get it from your Heroku Dashboard.

Paste API Key

Pick Heroku Application

We’re now presented with a list of our applications on Heroku. We’ll pick elixir-friends.

Pick Heroku Application

Name Your Server

The last step allows you to name your server.

Name Your Server

Awaiting First Deploy

Now that our deploy is set up, we’re prompted with a button that will allow us to deploy immediately. We’re also told that the next successful build of master will trigger this deployment.

Awaiting First Deploy

Deploying After Build Passes

Here we can see our next commit triggering a deployment after the CI build succeeded:

Deploying After Build Passes

Deploy In Progress

We can click the deployment that got started and see that it’s in progress. Here it’s actually queued up to start:

Deploy In Progress

Deploy Success

Finally, we can see that our automated deployment to Heroku was successful and our latest commit is now live on the site!

Deploy Success

Summary

So with that we went from an application that we had manually deployed to Heroku, to a rock solid CI + CD setup that we can use from now on. Semaphore made it very simple to set up, so someone without any experience with Continuous Integration or Continuous Deployment can just click through very straightforward wizards and get the same setup that I historically had to run fairly heavy infrastructure to support. On one hand, that seems so unfair! On the other hand, it means that we can avoid running this sort of infrastructure on our own for a lot of projects going forward. I hope you enjoyed it!

Bio

I’m Josh Adams, CTO of Isotope11 and the voice and keyboard behind ElixirSips. ElixirSips is a screencast series that can take you from Elixir newbie to experienced practitioner, as it walks through my entire experience with Elixir from my first bit of code through to building production applications. It contains over 22 hours of videos covering a wide variety of projects. If you’re interested in learning Elixir, give it a shot – I think it’s great! 🙂