Elixir/Phoenix Project: Ticket Workflow & CI Integration
Tags: elixir, tutorial, sideprojects
Published: 2020-09-29 14:11:17


#### Goals:
  - Create ticket workflow, convert notes to tickets
  - Integrate CI into the project

----

#### Create ticket workflow, convert notes to tickets
Although I am working on this new project solo and for the foreseeable future, I still wanted to have a way to create and track tasks. Back in the day, I used waffle.io but that project appears to have been axed. I liked waffle.io because of its Github integration and because it was relatively lightweight. I've used Jira and Atlassian, but those project managers seemed a bit heavy-handed for what I needed. After digging around a bit and asking some colleagues I settled on Github's own Issues and Projects. 

It seemed like a logical choice, the biggest win is that they are already a part of the repo, so its one less service I need to keep track of. It's also not any more complex than I need it to be, I can keep it lightweight and nimble. My current workflow is to first create an Issue ticket, mostly just a title, to get my thoughts documented. If I have notes at the time of creation I add them, if not I leave it blank. The order of the issue tickets is trivial, that's where Projects come in. Projects is basically a kanban board, like Trello, Jira, etc. My flow with the Project board is that I pull in 4-8 issue tickets at a time, so I can see a short runway, then move the ticket across the board as the task progresses. 

I recognize that I'm using both Issues and Projects at their minimum capacity, but at the moment that serves my needs. After all, I can always expand and modify my workflow, but this is a good starting point. The list of Issues for my project can be found [here](https://github.com/noelworden/atlas/issues), and the Project board [here](https://github.com/noelworden/atlas/projects/1)


#### Integrate CI into the project
This was a big one for me. A lot of the tutorials and walk-throughs I came across in [Part 1](https://dev.to/noelworden/part-1-setup-elixir-phoenix-project-5fpj) jumped from the creation of the project right into something like tweaking the CSS setup or generating the first migration. The longer a project goes on without incorporating some kind of CI (continuous integration), the bigger headache it is going to be to get the tests to pass. I feel like it's much better to get integration dealt with right out of the gate and _hopefully_ never have to think about it again.

Github has made it a lot easier than I had remembered to setup CI. The entire process can be done in the through Github web interface by clicking  `Actions > New workflow`. Github suggests an Elixir-based workflow, clicking `Set up this workflow` brought me to the Github editor, where it has a file named `elixir.yml` setup to be added to a new folder structure:

`./.gihhub/workflows/elixir.yml`

This is what the default file looks like:

{% gist https://gist.github.com/noelworden/123135829a2299214e59f24079bfcf7c %}

Referencing a [tutorial](https://hashrocket.com/blog/posts/build-the-ultimate-elixir-ci-with-github-actions#setting-up-mix-dependency-cache), I went ahead and added a formatting check to the end of the file:

{% gist https://gist.github.com/noelworden/b142ae21232f166e357c15a913081b9a %}

And committed the file via the Github web interface. At that point this was the entire `elixir.yml`

{% gist https://gist.github.com/noelworden/7273cfef2625cca6f76236a2249c3bf9 %}

On the first run of that CI configuration I got an error that my tests weren't passing. I did some research and found that I needed to add some code to include a database for the tests to run on:

{% gist https://gist.github.com/noelworden/59d02c5412b4a658b5a04832f4271797 %}

So, now the updated `elixir.yml` looks like this:

{% gist https://gist.github.com/noelworden/951cd3e8462138a39f9e314401fd900a %}

With that database setup, the tests passed, and I had that very satisfying green dot next to the pull request. Currently the CI was confirming that my tests pass and that the code was formatted properly. I was also interested in a service to analyze the code for consistency. I accomplished this by adding [Credo](https://github.com/rrrene/credo) to the project. Once included in the `mix.exs` file, Credo can be run locally with `mix credo` and it can be incorporated into the CI by adding the following line to `elixir.yml`:

{% gist https://gist.github.com/noelworden/74313b769fb9987bab46a57f5412fd5f %}

I added the `--strict` flag because I figure if I'm going to use a tool like this, I might as well use it to the fullest extent. With that addition, this is my final `elixir.yml` file:

{% gist https://gist.github.com/noelworden/d7b203cc4502e70a5b64c660c261817c %}

To my surprise, Credo actually found a few syntax errors in the Phoenix-generated code, so I ended fixing those and pushing up a small refactor commit to get the CI green again. It's worth noting that the compile time of Credo has slowed significantly with modern versions of Elixir, as noted in this [issue](https://github.com/rrrene/credo/issues/788). I'm not downgrading my Elixir version or doing anything to handle this, as it still meets my needs, and I have the time to wait for the checks to complete. 

#### Bonus - Include CI Status Badge in README
One of the articles I was referencing through this CI work also included an example of how to include the CI badge in the repo's README. I mean, why not? It will be pretty gratifying to see that green CI tag every time I'm in my repo. As far as the markdown goes, it's basically an image tag, being linked to a Github-generated `svg`. This is what my my image tag looks like:

{% gist https://gist.github.com/noelworden/72a0df5ce4b5d5017562093bd612e9f6 %}

I'll break it down, since it took me two commits to get it right:

A basic image tag in markdown is:

{% gist https://gist.github.com/noelworden/4836faa070f4807ec0700189b75640b3 %}

So, in the case of CI badge, the first chunk:

{% gist https://gist.github.com/noelworden/6527ead48ec37acc067145dc1ec6d2cc %}

Is declaring that its an image, and the alt text is `Elixir CI`. For what its worth, it would also work if the alt text were blank:

{% gist https://gist.github.com/noelworden/237c7b7d0a1f65cf056a69fb065dee64 %}

And the second chunk:

{% gist https://gist.github.com/noelworden/bfff1fee6440ff7fd8a1a63eb5a12fc5 %}

Is the source of the image file. The URL breaks down as such:

- `https://github.com/noelworden` -> my Github account
- `/atlas` -> the project repo
- `/workflows` -> the folder where the CI file is contained
- `/Elixir%20CI` -> the CI file I'd like to see the status of
  - It should be noted that its necessary to use URI-encoding to include the space in the `name` field of the file 

I didn't realize this until I had already coded it wrong once and merged it (:man_facepalming:), but that image link can be tested and confirmed in any markdown previewer.

#### Bonus - Create Pull Request Description Template
A pull request template wasn't any part of my original plan for this block of work, but I'm still figuring out my commit and pull request workflow. I had merged a handful of pull requests to get all of this CI work up and running correctly and realized that I should have been including the Issue number in the pull request descriptions. Knowing that I would forget to include that detail in future pull requests I figured it would be worth my time to incorporate a pull request template.

The file is a markdown file, that Github will look for when generating a new pull request. For Github to recognize it, the new file needed to be created and named: 

`PULL_REQUEST_TEMPLATE.md`

This file can be stored in any of the following places:

- the project root -> `atlas > PULL_REQUEST_TEMPLATE.md`
- in a `docs` folder -> `atlas > docs > PULL_REQUEST_TEMPLATE.md`
- in a hidden `.github` folder -> `atlas > .github > PULL_REQUEST_TEMPLATE.md`

In my original implementation of this template file I put it in the `docs` folder. But, as I write this and am thinking about it more, Im going to move it to the `.github` folder. The `.github` folder already exists because of the implementation of the CI workflow, and it feels more appropriate to have this Github-specific file there than in a `docs` folder.

In my case, I just wanted to ensure I always included the Issue number, so my template for the moment is simply one line:

{% gist https://gist.github.com/noelworden/3dc93540b8a9ee8d595ee7f6f0fc064d %}

But, of course, a template can as detailed as necessary for the given project. 

#### Closing thoughts
With these four items complete, I feel like my project is in the realm of _best practices_. I can create and track tasks, have continuous integration setup, and have the ability to run a linter locally. I can also see the status of the project's continuous integration at a glance, and have a simple pull request template setup. Since I'm in the mode of laying the groundwork for the project, the next step will be setting up a hosting environment. 

[This](https://github.com/noelworden/atlas/tree/6e1c8ab240fb65a0463bc938fa17ce57a8893c14) is what my repo looks like at the end of this block of work.

#### References
- https://docs.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#adding-a-workflow-status-badge-to-your-repository
- https://hashrocket.com/blog/posts/build-the-ultimate-elixir-ci-with-github-actions#setting-up-mix-dependency-cache
- https://lobotuerto.com/blog/elixir-continuous-integration-with-github-actions/
- https://docs.github.com/en/enterprise/2.15/user/articles/creating-a-pull-request-template-for-your-repository

------

This post is part of an ongoing [series](https://dev.to/noelworden/new-side-project-new-blog-series-135h). I encourage any critique, feedback, or suggestions in the comments.