[168] Continuous Integration

Using Semaphore CI to automatically test a Phoenix application each time we push new code.

Subscribe now

Continuous Integration [05.13.2016]

Continuous Integration is the process of merging code branches regularly. When people talk about Continuous Integration these days, they almost always are referring to it in conjunction with tests, of course. It does no good to be sure that your code merges cleanly if it no longer performs the desired task!

Today's episode is going to cover performing Continuous Integration in Elixir by way of the Semaphore hosted Continuous Integration service, running the tests for a Phoenix application. Let's get started.


We're going to start a new Phoenix project whose purpose is to collect images from twitter that are tagged with #elixirfriends and collect them. We'll not build the Twitter integration yet, but we'll build the Phoenix application that can display the data.

mix phoenix.new elixir_friends
cd elixir_friends
mix phoenix.server

((( visit http://localhost:4000 )))

Alright, so here's a new phoenix app using the latest version of the framework. Now let's use its generators to build a quickie data model for the images:

mix phoenix.gen.html Post posts image_url:string content:string source_url:string

So we'll just call these Posts, that have an image_url, some content, and a source_url. It's not a crazy complicated data model but this is a quick thing we want to deploy so no big deal.

Let's add the resource to the router:

  scope "/", ElixirFriends do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
    resources "/posts", PostController

Then we'll create the database and migrate it up:

mix ecto.create
mix ecto.migrate

OK, so now there are some posts that can be created. Let's look at that:

((( http://localhost:4000/posts )))

We'll make a post:

((( do it, using: image_url: http://fc00.deviantart.net/fs71/i/2012/176/8/f/marvin_the_paranoid_android_by_wouthezx-d54uny0.jpg content: Marvin the Martian source_url: http://elixirsips.com )))

OK, so this works and we'll visit it at the show url:

((( do it )))

Right, so we want this to show the image in an image tag, and link to the source. We'll define this desire in the controller test for now. Let's say that the show page ought to have an image tag with our image's source. Open up test/controllers/post_controller_test.exs:

  test "shows an image for the post", %{conn: conn} do
    post = Repo.insert %Post{image_url: "http://fc00.deviantart.net/fs71/i/2012/176/8/f/marvin_the_paranoid_android_by_wouthezx-d54uny0.jpg"}
    conn = get conn, post_path(conn, :show, post)
    assert html_response(conn, 200) =~ "Show post"
    assert html_response(conn, 200) =~ "<img src='http://fc00.deviantart.net/fs71/i/2012/176/8/f/marvin_the_paranoid_android_by_wouthezx-d54uny0.jpg' />"

Run the tests, and they'll fail. Let's fix the template.

<h2>Show post</h2>

<img src='<%= @post.image_url %>' />

Run the test again, and it passes. Now this isn't anything fancy, but it's a start. Now let's see about using Semaphore to run the tests everytime we commit changes to this project. First I'll create it on github:

git init .
git add .
git commit -m"Initial checkin"
hub create
git push origin master

OK, so now it's up on GitHub. Next we'll pull up Semaphore CI where I'm logged in already. Let's add a new project.

((( do it )))

It takes quite a while to list my projects because I have like 400 of them. We'll find elixir_friends in the list ((( use ctrl+f to find it )))

OK, so we'll just click through and it will see it's an elixir project. We can continue, and the predefined settings would work for a basic elixir library or something like that. Since we have a Phoenix application though, we need a postgres database. Semaphore provides the database username and password as environment variables, so we'll provide for that in our test configuration:

  username: System.get_env("DATABASE_POSTGRESQL_USERNAME") || "postgres",
  password: System.get_env("DATABASE_POSTGRESQL_PASSWORD") || "postgres",

We'll push up again, and now our tests are passing. Now every time we push to our GitHub repo, Semaphore's running our tests. Fantastic.


In today's episode we saw how to use Semaphore CI to run our Phoenix application's integration tests every time we push new commits. We'll look at following the build up with a Heroku deploy for Continuous Deployment in a later episode. See you soon!