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.
Selecting Your Repository Host
Semaphore provides nice integration with various potential repository hosts. Our app is on GitHub, so we’ll pick that:
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:
Select Branch
Your branches will be listed, and you can choose the branch you care about:
Select Account
Next, you choose your Semaphore Account. I only have one:
Analysis
This is one of the coolest features of Semaphore. It will analyze the project to determine which kind of project it is.
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.
First Build
Once you’ve OKed the Build Plan, your first build is kicked off immediately:
Our First Build Fails
Our first build fails…you can see in the browser why it failed:
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:
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:
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.
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.
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.
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.
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.
Pick Heroku Application
We’re now presented with a list of our applications on Heroku. We’ll pick elixir-friends.
Name Your Server
The last step allows you to 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.
Deploying After Build Passes
Here we can see our next commit triggering a deployment after the CI build succeeded:
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 Success
Finally, we can see that our automated deployment to Heroku was successful and our latest commit is now live on the site!
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! 🙂