AzureDevOps, Elixir, Docker, CI/CD, and the others - Part 1: docker-compose and testing.
Tags: elixir, phoenix, cicd, azuredevops
Published: 2019-11-08 13:49:47

##The Problem

Elixir is a new player in the market, and the tooling is not as comprehensive as the others like C# and Java. When I started learning Elixir, I had some questions like:
* Where to host it?
* How to build and test it in a CI style?
* How to deploy it on Azure?

The immediate answer was to have a VM on Azure, but that's not an affordable solution. Fortunately, nowadays the main problem is solved by using docker for development and deployment. In this post, I will share a simple solution to using AzureDevOps for the CI part of the development and in a follow-up article, I will cover the CD part. If you want to check out the code, here is the repo: https://github.com/benyblack/elixir-phoenix-ci.

One of the most popular approaches to website creation in Elixir is by using Phoenix. To set it up using [this](https://gist.github.com/benyblack/f3c0e44fa8f796e95644da0bfbb4c6ff) gist. The credentials for the __Postgres server__ exist in __dev.exs__ in the config folder. If your credentials are different, you can change them in the script Have a look at the final result in the following:

{% asciinema 279787 %}

Navigate to http://localhost:4000, and you will see something like this:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/bz53zxq5xtoifat4f67f.png)

Now that we have a working code, then we can think about the build and test part. To begin, let's try to do it locally with Docker. 

First, we need a docker file:
{% gist https://gist.github.com/benyblack/41f05c2d1d128483528ce91573253de4 %}

Build and run it by these commands:

```shell
docker build -t benyblack/helloworldci .
docker run --rm -p 4000:4000 benyblack/helloworldci
```

Navigate to http://localhost:4000, and you should get see a working web site, albeit one with lots of connection errors in the console. It's time to use docker-compose magic. The config file for docker-compose is rather simple:

{% gist https://gist.github.com/benyblack/bc30bbe100326e6b27a8d4fb746025ec %}

Furthermore, we need to change the database __hostname__ in __test.exs__. Change the __hostname__ to __database__. Then run this command to build and run our tests:

```shell
docker-compose up --abort-on-container-exit
```
There we have it! You should see the result at the end of the console messages:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/h3lh6oal8joywz6bahgy.png)

##Continuous Integration
That's it! It's now ready to be used in AzureDevOps. We need to connect our GitHub and DockerHub account to the project in the AzureDevOps project settings section. Go to the __Project Settings__ at the bottom left side of the page and then select __Service connections__ and hit "__+ New service connection__". From the list select __Github__. It is necessary to give access to our code on Github.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/im0g12oktytyszhzd8aa.png)
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/carvus2f98y2i4msqgw8.png)

Do the same for DockerHub to connect your public repositories to the project, except select __Docker Registery__ this time. We'll use it later for using docker-compose.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/1iqhmawdw934auyae4cs.png)
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/d2mafy1nhal8dqu74ou3.png)

The next step is to create a Pipeline. Go to __Pipelines__ from the main menu. Select __Github__ from the list.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/7nt3sdv2k1fvxlryyriy.png)

Hit __Next__ and select __Existing Azure pipelines YAML file__.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/n4en6tw77hyzr1robn88.png)

A popup should appear from the right. Select the config file we have created.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/eamk6ewk0i0ny5rhyn2p.png)

Then, you can adjust the config by hitting the setting link or editing it manually. If your DockerHub connection name is not the same as mine, you'll have to change it.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/5idpe5chc6flgznxpl2m.png)
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/8zuxvupqucbkc9oslegz.png)

Finally, hit the __Run__ button at the top left of the page.

You should see something like this:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/5c5z87qz8dp11j3arx6x.png)

At long last, we have to have some green lights. However, there is one more step; publishing the test result. The problem is that AzureDevOps can't parse the test result from the __mix test__. The solution is to apply a __Formatter__ for the test result. In this case, I chose to use [JUnitFormatter](https://github.com/victorolinasc/junit-formatter). It exports the result to an XML file. Using the library is pretty straightforward. I appended this section in my __test.exs__ in the config folder:

```yaml
# Configure publishing test result
config :junit_formatter,
report_file: “report_file_test.xml”,
report_dir: “./”,
print_report_file: true,
prepend_project_name?: true
```

Moreover, we need to add a test publishing step to our pipeline. Go to the build menu and select Edit to edit the pipelines. From the right panel, select __Publish Test Result__ and set the __testResultsFiles__ to '__**/hello_world_ci-report_file_test.xml__'. Click __Add__. It should look like this:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ojk8zif7bljf41j00vvb.png)

Save it and run it again. You should see something like this:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/mcetvol54e04pmld87te.png)

Go to the __Tests__ tab. Your Tests tab should be the same as mine:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/suzuuhm8pp1aoiitty0e.png)

Voilà! That's it! Pretty simple. In an [upcoming post](https://dev.to/behnam/azuredevops-elixir-docker-ci-cd-and-the-others-part-2-release-and-deploy-3c09), I am going to do the __CD__ part.