<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Patricio Cano</title>
    <description>The latest articles on DEV Community by Patricio Cano (@suprnova32).</description>
    <link>https://dev.to/suprnova32</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F18659%2F25345672-34b1-4431-ab71-b7b4f85a0db3.jpeg</url>
      <title>DEV Community: Patricio Cano</title>
      <link>https://dev.to/suprnova32</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/suprnova32"/>
    <language>en</language>
    <item>
      <title>AlloyCI - A year since release</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Fri, 14 Sep 2018 02:15:09 +0000</pubDate>
      <link>https://dev.to/suprnova32/alloyci---a-year-since-release-7ph</link>
      <guid>https://dev.to/suprnova32/alloyci---a-year-since-release-7ph</guid>
      <description>&lt;p&gt;It has been over a year since I started working on &lt;a href="https://github.com/AlloyCI/alloy_ci"&gt;AlloyCI&lt;/a&gt;, but today is the one year anniversary from its first public release, and a lot has happened since then.&lt;/p&gt;

&lt;p&gt;I would like to tell you more about the project, what motivated me to start it, and what has kept me going since. I would have hoped to release version 1.0 by now, but alas life had other plans. Keep on reading for more...&lt;/p&gt;

&lt;h3&gt;
  
  
  How everything started
&lt;/h3&gt;

&lt;p&gt;I know I mentioned this on other posts about AlloyCI, but I want to state it again. I started the project as a learning exercise and as a challenge to myself. I heard so many good things about Elixir, but I was happy with Ruby, so I saw no real incentive for me to learn it. That was a mistake. Once you stop learning, you start going backwards as a developer.&lt;/p&gt;

&lt;p&gt;The tipping point for me was when I left GitLab. I found myself with a lot of time on my hands while looking for a new job. It was the perfect time to learn something new. I picked up a few books on Elixir, and Phoenix, and started dipping my toes in the water. &lt;/p&gt;

&lt;p&gt;After so many years working on just Ruby, Elixir felt familiar, but at the same time it felt like a breath of fresh air, something I hadn't felt since I started learning Ruby back in 2012. The feeling wasn't quite the same, though. Before Ruby I was using Java at university, and only Java, as classes were very much enterprise and industry focused. At that time, Ruby liberated me from the clutches of "enterprise grade" programming. It helped me see that actual joy could be had while developing software, that code could be beautiful, and it showed me a great and welcoming community.&lt;/p&gt;

&lt;p&gt;So when I started learning Elixir, it wasn't like being in a dark tunnel for ages and finally seeing the light, like it was when going from Java to Ruby. It felt like going from watching a movie on a regular cinema to watching it in an IMAX theater with digital projection and Dolby Atmos surround sound. Both high quality experiences, but once you experience the latter, going to the former feels like going back to the stone age.&lt;/p&gt;

&lt;p&gt;Once I started learning all the great things that Elixir, and the Erlang ecosystem have to offer, and not only that but the incredibly amazing, kind, and helpful community, I knew I had found something special, and that I made a mistake not diving into Elixir the minute I heard about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The project idea
&lt;/h3&gt;

&lt;p&gt;If you've read AlloyCI's dev diaries (which I have neglected since the last one I wrote, I know) you know how the idea got started, but if you haven't, here is the gist of it. I wanted to build something bigger than the tutorial projects, and I wanted to see if I could create a worthwhile and hopefully long lasting open source project. &lt;/p&gt;

&lt;p&gt;AlloyCI came out of that. I wanted to work on something a bit more complex, but also a bit familiar, so I chose a continuous integration system.&lt;/p&gt;

&lt;h3&gt;
  
  
  First couple of months
&lt;/h3&gt;

&lt;p&gt;Initial development went pretty quickly and I was able to get a working prototype in a couple of weeks, but it took me almost 6 months to release the first public version, since that was the first MVP, where the basic CI system worked and it looked kind of nice.&lt;/p&gt;

&lt;p&gt;Since then, new versions where released pretty often, around once a month for the next 9 months, until v0.7.0 which was released almost 3 months ago.&lt;/p&gt;

&lt;p&gt;My motivation was high during that time, which meant coding was easy, even on times where I hit a snag, or things got difficult, that motivation kept me going. Even while I started to get frustrated with my day to day work, my drive to continue working on AlloyCI did not wither.&lt;/p&gt;

&lt;p&gt;But motivation can be hard to maintain, and that is the situation in which I found myself at the beginning of the summer. My frustration grew larger, to the point where it started sucking all my will to write software. I needed a break.&lt;/p&gt;

&lt;h3&gt;
  
  
  Last couple of months
&lt;/h3&gt;

&lt;p&gt;I needed a break from a lot of things, so I took the time. It is important to take care of oneself, so I decided to not pressure myself, distance myself from the project, and only do something if I really felt like it. This approach helped a lot.&lt;/p&gt;

&lt;p&gt;In the time since the last release, and until a couple of weeks ago, I barely touched the code, and it was mostly to update dependencies, or Elixir versions.&lt;/p&gt;

&lt;p&gt;I regained my motivation at the beginning of the month and started working on a new feature that was on the roadmap. It took me a while to get back in the rhythm, but it was awesome to be back. &lt;/p&gt;

&lt;p&gt;I picked up the rhythm again, and noticed a lot of chores that needed to be done, in order to make developing AlloyCI easier, so I did them 😊&lt;/p&gt;

&lt;p&gt;Things like adding &lt;code&gt;typespecs&lt;/code&gt; to public functions, refactoring modules, improving the way the build traces are saved, etc. I started having fun again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Present
&lt;/h3&gt;

&lt;p&gt;Interest in CI/CD tools has picked up, specially now that Microsoft announced their entry with &lt;a href="https://azure.microsoft.com/en-us/services/devops/pipelines/"&gt;Azure Pipelines&lt;/a&gt;, so I think it's time to take AlloyCI more seriously, and not just as a hobby project. I would like to make it a worthwhile open source option for CI/CD, and for that I need v1.0 to be out sooner rather than later.&lt;/p&gt;

&lt;p&gt;Which is why, with this post, I'd also like to announce the release of AlloyCI v0.8.0. A proper announcement post is coming later today or tomorrow with a detailed description of the changes, but you can already see what changed here: &lt;a href="https://github.com/AlloyCI/alloy_ci/blob/master/CHANGELOG.md"&gt;CHANGELOG.md&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The next year
&lt;/h3&gt;

&lt;p&gt;Getting to 1.0 is going to be a lot of work. There are a lot of features that are missing, specially surrounding administration, user management, permissions, etc., in short, almost everything that an organization will need to run AlloyCI as a serious development tool. It will take me the better part of the next year to get there, but I am hoping that someone awesome (maybe you) would jump in and help the project grow.&lt;/p&gt;

&lt;p&gt;A long time has gone by since the last time I posted a dev diary. I have wanted to document most of the development process, so I will be writing these posts again. I have learned a lot this past year, and I want to share my knowledge with as much people as I can.&lt;/p&gt;

&lt;p&gt;These are my goals for the second year of AlloyCI, I really hope I can meet them, and we will be reviewing them soon enough.&lt;/p&gt;

&lt;p&gt;For me this year has been full of ups and downs, a couple of more downs than ups actually, but I know it will get better. I am setting goals for my personal and professional lives and also setting a very ambitious goal for this project. To me AlloyCI feels like my baby sometimes, and I know we both will grow stronger this year!&lt;/p&gt;

&lt;h4&gt;
  
  
  Bonus trivia
&lt;/h4&gt;

&lt;p&gt;AlloyCI was released on September 13th because that is also my birthday. I released it as a present to myself, to show to myself that I could create something great, and to put myself out there. So happy birthday to AlloyCI 🎉 Thank you for this year! 🎉🎊&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>opensource</category>
      <category>motivation</category>
      <category>career</category>
    </item>
    <item>
      <title>AlloyCI v0.7.0 released!</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Tue, 26 Jun 2018 23:02:37 +0000</pubDate>
      <link>https://dev.to/supernova32/alloyci-v070-released-360a</link>
      <guid>https://dev.to/supernova32/alloyci-v070-released-360a</guid>
      <description>

&lt;p&gt;AlloyCI v0.7.0 has been released! This version includes some &lt;em&gt;major&lt;/em&gt; changes. Keep reading for a better description, or go &lt;a href="https://github.com/AlloyCI/alloy_ci/releases/tag/v0.7.0"&gt;here&lt;/a&gt; to checkout the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deprecations
&lt;/h2&gt;

&lt;p&gt;The biggest change for this release is the fact that JSON configuration files have been deprecated. You will no longer be able to use them to configure your AlloyCI builds. From now on you will need a YAML configuration file.&lt;/p&gt;

&lt;p&gt;The main reason behind this decision is that YAML is much more flexible than JSON. It allows us to use aliases in oder to avoid duplication, to add comments to make the config file more understandable, and it is the de facto standard configuration file for almost all CI systems in the market.&lt;/p&gt;

&lt;p&gt;When I first started writing AlloyCI, my initial intention was to use YAML for the configuration files, but at that time, the YamlElixir library did not support all modern YAML features. A couple of months ago these features were added to the library, but it still lacked proper support for aliases. I decided to see how difficult it would be to add that functionality. Luckily it was quite simple, so now AlloyCI uses its own &lt;a href="https://github.com/AlloyCI/yaml-elixir"&gt;fork of the YamlEixir library&lt;/a&gt; with &lt;a href="https://github.com/AlloyCI/yaml-elixir/commit/9086dbb4c46adbb5e2e140b00a3bb16c656586aa"&gt;proper support for aliases&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Furthermore, YAML makes the configuration file easier to write and easier to read. As an example, here is the config file used for AlloyCI in JSON format:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"elixir:latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"postgres:9.6"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"_build/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"deps/"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"variables"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"MIX_ENV"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"GITHUB_CLIENT_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fake-id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"GITHUB_CLIENT_SECRET"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fake-secret"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"GITHUB_SECRET_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fake-token"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"SECRET_KEY_BASE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NULr4xlNDNzEwE77UHdId7cQU+vuaPJ+Q5x3l+7dppQngBsL5EkjEaMu0S9cCGbk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres://postgres@postgres:5432/alloy_ci_test"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"before_script"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"mix local.hex --force"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"mix local.rebar --force"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"mix deps.get"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"mix ecto.setup"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"mix + coveralls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"stage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"elixir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"postgres"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"script"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mix coveralls.post --branch &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CI_COMMIT_REF_SLUG&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; --name &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CI_SERVER_NAME&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; --sha &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CI_COMMIT_SHA&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; --committer &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CI_COMMIT_PUSHER&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; --message &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CI_COMMIT_MESSAGE&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"credo + formatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"stage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"elixir"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"script"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mix credo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"mix format --check-formatted"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here is the exact same config in YAML:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:latest&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres:9.6&lt;/span&gt;

&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;_build/&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deps/&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MIX_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;GITHUB_CLIENT_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fake-id&lt;/span&gt;
  &lt;span class="na"&gt;GITHUB_CLIENT_SECRET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fake-secret&lt;/span&gt;
  &lt;span class="na"&gt;GITHUB_SECRET_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fake-token&lt;/span&gt;
  &lt;span class="na"&gt;SECRET_KEY_BASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NULr4xlNDNzEwE77UHdId7cQU+vuaPJ+Q5x3l+7dppQngBsL5EkjEaMu0S9cCGbk&lt;/span&gt;
  &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres://postgres@postgres:5432/alloy_ci_test&lt;/span&gt;

&lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix local.hex --force&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix local.rebar --force&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix deps.get&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix ecto.setup&lt;/span&gt;

&lt;span class="s"&gt;mix + coveralls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elixir&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix coveralls.post --branch "$CI_COMMIT_REF_SLUG" --name "$CI_SERVER_NAME" --sha&lt;/span&gt;
    &lt;span class="s"&gt;"$CI_COMMIT_SHA" --committer "$CI_COMMIT_PUSHER" --message "$CI_COMMIT_MESSAGE"&lt;/span&gt;

&lt;span class="s"&gt;credo + formatter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elixir&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix credo&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix format --check-formatted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Much cleaner, right?&lt;/p&gt;

&lt;p&gt;Also, YAML allows you to use comments in your file, which means that if you have a particularly complex setup, you can leave comments in them to make it easier to understand for people new to the project.&lt;/p&gt;

&lt;p&gt;In addition to that, YAML allows you to declare aliases in your file, like a generic part, that can be reused in other declarations in order to avoid extra typing, e.g.:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:latest&lt;/span&gt;

&lt;span class="c1"&gt;# This is the generic part we want to reuse.&lt;/span&gt;
&lt;span class="s"&gt;.docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;docker&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:1.5&lt;/span&gt;
  &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/bin/bash"&lt;/span&gt;

&lt;span class="na"&gt;mix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# In here he use that generic part, so everything declared there, will be added here&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*docker&lt;/span&gt;
  &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres:9.6&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elixir&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix test&lt;/span&gt;

&lt;span class="na"&gt;credo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Same goes for here&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*docker&lt;/span&gt;
  &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres:latest&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis:latest&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elixir&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix credo&lt;/span&gt;

&lt;span class="c1"&gt;# This one does not use the generic part, so it will use the `image` declared in the first line&lt;/span&gt;
&lt;span class="na"&gt;distillery&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;elixir&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;MIX_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prod&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mix docker.build --tag latest&lt;/span&gt;
  &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;alloy_ci.tar.gz&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;_build/prod/lib/alloy_ci&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And AlloyCI is smart enough not to treat elements starting with a &lt;code&gt;.&lt;/code&gt; as a build directive, so no build named &lt;code&gt;.docker&lt;/code&gt; will be created. &lt;/p&gt;

&lt;p&gt;I'm sure using YAML will make AlloyCI a lot friendlier and easier to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  New Features
&lt;/h2&gt;

&lt;p&gt;This release does not include many new features. The most notorious one is that the status of pipelines and builds will be automatically updated via websockets in their own respective page.&lt;/p&gt;

&lt;p&gt;This means that whenever you are in the project view (to see a list of pipelines) or on the pipeline view (to see a list of build jobs) the status of each one will be automatically updated whenever their status changes on the backend. This is accomplished via Phoenix Channels. You can see the changes necessary for this to work &lt;a href="https://github.com/AlloyCI/alloy_ci/commit/0f2fd7f0ae29254bec1e69019f9c66295afa61a4"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug fixes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fixed redirect loop that would happen when an authentication token expires.&lt;/li&gt;
&lt;li&gt;Reverted back to Kerosene v0.7.0, as the updated v0.8.0 had pagination bugs.
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thank you for your interest on AlloyCI, and I hope you find this update useful. As always don't hesitate to ask any question, or report any bugs via the issue tracker on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Check out AlloyCI v0.7.0! &lt;a href="https://github.com/AlloyCI/alloy_ci/releases/tag/v0.7.0"&gt;https://github.com/AlloyCI/alloy_ci/releases/tag/v0.7.0&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🎉🐣&lt;/p&gt;


</description>
      <category>elixir</category>
      <category>opensource</category>
      <category>ci</category>
      <category>projectupdate</category>
    </item>
    <item>
      <title>AlloyCI v0.6.0 released!</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Mon, 07 May 2018 21:56:39 +0000</pubDate>
      <link>https://dev.to/supernova32/alloyci-v060-released-3h94</link>
      <guid>https://dev.to/supernova32/alloyci-v060-released-3h94</guid>
      <description>

&lt;p&gt;AlloyCI v0.6.0 has been released. The biggest change since last release is that it now supports any S3 compatible storage service, in order to store the build artifacts that might have been generated by your project.&lt;/p&gt;

&lt;p&gt;This also means that now you can make full use of this feature even in you are running AlloyCI on Heroku.&lt;/p&gt;

&lt;p&gt;Check it out! &lt;a href="https://github.com/AlloyCI/alloy_ci/releases/tag/v0.6.0"&gt;https://github.com/AlloyCI/alloy_ci/releases/tag/v0.6.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎉🐣&lt;/p&gt;


</description>
      <category>elixir</category>
      <category>ci</category>
      <category>projectupdate</category>
    </item>
    <item>
      <title>AlloyCI v0.5 released!</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Fri, 30 Mar 2018 22:51:24 +0000</pubDate>
      <link>https://dev.to/supernova32/alloyci-v05-released-3m7p</link>
      <guid>https://dev.to/supernova32/alloyci-v05-released-3m7p</guid>
      <description>&lt;h2&gt;
  
  
  Major changes ahead
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Abt7Q3HsTcw86TB_q7mlz2A.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Abt7Q3HsTcw86TB_q7mlz2A.jpeg"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/zepnJQycr4U?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Kristopher Roller&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/sky?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This week marks the first year anniversary since the &lt;a href="https://github.com/AlloyCI/alloy_ci/tree/b828881ea982f1a8598aa8f7282e96fa72c55498" rel="noopener noreferrer"&gt;first commit&lt;/a&gt; of AlloyCI, and to celebrate it, we are releasing the v0.5 version. With it we get closer to the much coveted v1.0 release, when AlloyCI will be fully ready (and fully supported) for production environments.&lt;/p&gt;

&lt;p&gt;This version of AlloyCI comes with a wide variety of changes. The most noticeable being the new and improved design, and support for &lt;strong&gt;GitHub Enterprise.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Design Changes
&lt;/h4&gt;

&lt;p&gt;For the past year we have been using CoreUI as the basis of the design. At the beginning, it seemed like a good “admin” template that offered a lot of functionality. Unfortunately it started to feel dated, and bloated pretty quickly. The way it was used with AlloyCI was not ideal and it was not nice to look at.&lt;/p&gt;

&lt;p&gt;We decided it was time for a change. The new design feels clean, modern, and is easy to look at.&lt;/p&gt;

&lt;p&gt;Some elements remained, like the use of cards to represent the projects, and the use of panels to separate related information:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A4u-xEARFvrf1VO-1TxZZeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A4u-xEARFvrf1VO-1TxZZeA.png"&gt;&lt;/a&gt;New projects view&lt;/p&gt;

&lt;p&gt;The use of colors to represent statuses also stayed, but with a new pantone:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AxBvkdVgChmfrMXbXPI5Ncg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AxBvkdVgChmfrMXbXPI5Ncg.png"&gt;&lt;/a&gt;New pipelines view (single project)&lt;/p&gt;

&lt;p&gt;The builds view was completely reworked to better illustrate the different stages of a pipeline, and to give a quick overview of the status of each build within that pipeline:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A0kgvZcdJPxPNCd_VkYVPMw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A0kgvZcdJPxPNCd_VkYVPMw.png"&gt;&lt;/a&gt;New builds view (single pipeline)&lt;/p&gt;

&lt;p&gt;The single build view also suffered major changes. Now each build has its own page, with dedicated, always visible information about the build on an aside to the left, and the entire build output (which will automatically update if the build is running) to the the right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ABSgWvitIiLzFkmlBgnoTiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ABSgWvitIiLzFkmlBgnoTiw.png"&gt;&lt;/a&gt;New build view&lt;/p&gt;

&lt;p&gt;The project settings view did not change that much, but it still looks cleaner and now groups related information more tightly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8Q5jE1HpzPISdPgxMXiM_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A8Q5jE1HpzPISdPgxMXiM_w.png"&gt;&lt;/a&gt;Project settings view&lt;/p&gt;

&lt;h3&gt;
  
  
  New features
&lt;/h3&gt;

&lt;h4&gt;
  
  
  GitHub Enterprise
&lt;/h4&gt;

&lt;p&gt;This new version of AlloyCI also comes with a host of new features. The biggest one for this release is support for &lt;strong&gt;GitHub Enterprise.&lt;/strong&gt; GitHub released version 2.13 a few days ago with support for GitHub Apps. This meant that AlloyCI would finally be compatible with GHE. After a few changes to the way the system communicates with GitHub, mainly making endpoints configurable, full compatibility was achieved.&lt;/p&gt;

&lt;h4&gt;
  
  
  Builds
&lt;/h4&gt;

&lt;p&gt;Builds can now be restarted individually, without having to restart the entire pipeline. The old build data will be kept, and a new job will be created for the new build.&lt;/p&gt;

&lt;h4&gt;
  
  
  Build Artifacts
&lt;/h4&gt;

&lt;p&gt;The other major new features revolve around build artifacts. With this release we added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Artifacts can be managed and downloaded from the build view&lt;/li&gt;
&lt;li&gt;Expired artifacts will be pruned once a day (or at any configurable interval)&lt;/li&gt;
&lt;li&gt;Artifacts can be kept forever, if the user chooses to&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bug fixes
&lt;/h3&gt;

&lt;p&gt;A couple of bugs have also been fixed with this release:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When cancelling a pipeline, all builds were marked as cancelled, now only builds that are either created, running, or pending are updated.&lt;/li&gt;
&lt;li&gt;After the upgrade to Guardian 1.0, it became impossible to add another authentication method to an existing user. This has been fixed.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This is pretty much it for this release. The roadmap ahead includes adding S3 bucket support for build artifacts, so that they can be uploaded to services like AmazonS3, or Digital Ocean Spaces. With this support implemented, it will become possible for AlloyCI installations that are hosted on Heroku to also make use of build artifacts, something that is not possible right now.&lt;/p&gt;

&lt;p&gt;Until next time! ❤️&lt;/p&gt;

</description>
      <category>ci</category>
      <category>elixir</category>
      <category>phoenix</category>
      <category>opensource</category>
    </item>
    <item>
      <title>AlloyCI Dev Diary — Part 3</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Mon, 26 Mar 2018 17:17:18 +0000</pubDate>
      <link>https://dev.to/suprnova32/alloyci-dev-diary--part-3-20a3</link>
      <guid>https://dev.to/suprnova32/alloyci-dev-diary--part-3-20a3</guid>
      <description>&lt;h1&gt;
  
  
  Project management with GitHub Issues &amp;amp; Boards
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2At3A-s2eExektSb4S48r0FQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2At3A-s2eExektSb4S48r0FQ.jpeg"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/IClZBVw5W5A?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Todd Quackenbush&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/management?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of a series of posts detailing the development process of AlloyCI. The previous entries have been:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/supernova32/alloyci-dev-diary---part-1--1ai9"&gt;Part 1: Starting a new Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/supernova32/alloyci-dev-diarypart2-1jfl"&gt;Part 2: Structuring a new Phoenix Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have started a new project, we most certainly have a lot on our minds about what needs to be done. We might already know where to start, what comes next, and how to get there, or we might not.&lt;/p&gt;

&lt;p&gt;If we already know what we want, it makes perfect sense to write it down, give it form, and expand on the ideas and use cases we want to tackle.&lt;/p&gt;

&lt;p&gt;If we don’t, then writing down the goals we want to accomplish will most likely light the way. Once we have written the main goal, the next step would be to break it down into smaller goals, and the those goals into smaller tasks that we can accomplish easily.&lt;/p&gt;

&lt;p&gt;In both cases, we need a way to keep track of what we need to work on. For a software project, GitHub issues are a great tool for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organization
&lt;/h2&gt;

&lt;p&gt;You can create an issue for every task that needs to be tackled, keep them, organized using labels, e.g. have a label for User related, or front-end related tasks, and to keep a record of your progress.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcqR7MXpXmO8dx5qmWr3p4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcqR7MXpXmO8dx5qmWr3p4A.png"&gt;&lt;/a&gt;AlloyCI’s Issue Labels&lt;/p&gt;

&lt;p&gt;I have been using them for AlloyCI since early on. The project has different labels to organize different issues, and filter them. Even though, for now, it’s only me working on AlloyCI, having all the tasks that need tackling, and also a history of what has already been done, will really help anyone wanting to get started with the project.&lt;/p&gt;

&lt;p&gt;It might seem tedious if it’s only you working on a project to devote so much time to issues, but it will really help. You will most likely be the one that benefits the most once you come back after a few months of not working on the project and see the list of thing to be done. If you hadn’t written them down, you would have most likely forgotten about this tiny feature you wanted to add, that seems unimportant but greatly increases user’s happiness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Planning
&lt;/h2&gt;

&lt;p&gt;If you want to go a step further and keep track of what issues are being worked on, what their statuses are, and what the next steps are, you can use GitHub’s Issue Boards. The Boards allow you to create columns that represent stages of the development process, like “In Progress”, “Waiting Review”, “To Be Deployed”, etc. They give you an instant visual overview of how the project is progressing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9WE_jlkGoe7_o_L360e5zQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9WE_jlkGoe7_o_L360e5zQ.png"&gt;&lt;/a&gt;AlloyCI’s Issue Board&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting goals
&lt;/h2&gt;

&lt;p&gt;To keep myself motivated I also added milestones to the issues. The first milestone was v0.1, in other words, the minimum amount of functionality needed in order for AlloyCI to actually be a CI coordinator. I set a date for it, as a tentative goal for when I wanted to be done with the first part. I wasn’t able to keep it (I pushed it back at least 2 times and by more than 2 months), but it gave me something to aim for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0Qa02HlJVbY2jM3t4Ge9Hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A0Qa02HlJVbY2jM3t4Ge9Hg.png"&gt;&lt;/a&gt;AlloyCI’s current milestones&lt;/p&gt;

&lt;p&gt;For v1.0 I haven’t set a date, it is an open milestone, because there are some pretty complex issues assigned to it, but I still look at it as a goal. That is where I want the to project to be. It can be in a few months, in can be next year, but I &lt;em&gt;know&lt;/em&gt; I’m going to get there.&lt;/p&gt;

&lt;p&gt;There are many tools to help you with project management, but for a small team (or a team of one) the tools GitHub gives you for free are more than enough to get you where you need to be.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>opensource</category>
      <category>devdiary</category>
      <category>mangement</category>
    </item>
    <item>
      <title>AlloyCI Dev Diary — Part 2</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Thu, 22 Mar 2018 23:20:58 +0000</pubDate>
      <link>https://dev.to/suprnova32/alloyci-dev-diarypart2-1jfl</link>
      <guid>https://dev.to/suprnova32/alloyci-dev-diarypart2-1jfl</guid>
      <description>&lt;h1&gt;
  
  
  Structuring a new Phoenix Project
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1440613740265-a37aa8a61131%3Fixlib%3Drb-0.3.5%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26s%3D78b205db80905893f41d2f694258e376%26auto%3Dformat%26fit%3Dcrop%26w%3D2674%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1440613740265-a37aa8a61131%3Fixlib%3Drb-0.3.5%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26s%3D78b205db80905893f41d2f694258e376%26auto%3Dformat%26fit%3Dcrop%26w%3D2674%26q%3D80" alt="Photo by valor kopeny on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This blog post is part of a series of posts detailing the development process of AlloyCI. The previous entries have been:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/supernova32/alloyci-dev-diary---part-1--1ai9"&gt;Part 1: Starting a new Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you are coming from a Rails background, you might find the folder structure of a Phoenix project a bit weird, specially after the changes in 1.3. But don’t be put off by this, the structure actually makes a lot of sense, specially the new 1.3 structure.&lt;/p&gt;

&lt;p&gt;Unlike Rails, there is no &lt;code&gt;app/&lt;/code&gt; folder where most of your code will live. Phoenix 1.3 projects follow the structure of pretty much any regular Elixir project, this means that most of your code will live inside the &lt;code&gt;lib/my_app&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;As you might now, Phoenix 1.3 changed the way projects are structured. Before this change most of your code would be under &lt;code&gt;web/&lt;/code&gt;, with little to no further organizations. You would have a models directory, where you would put all your business logic, without much consideration as to how they interact together. This folder would get pretty large, pretty fast. Also the name model seems to imply an object, but in Elixir, there are no objects, so storing your data access layer under a folder named "models" makes little contextual sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data &amp;amp; Contexts
&lt;/h2&gt;

&lt;p&gt;Phoenix 1.3, by default, guides you towards a better way of organizing your code. Controllers, Views, Templates go under &lt;code&gt;lib/my_app_web&lt;/code&gt;, database migrations and related files go under &lt;code&gt;priv/repo&lt;/code&gt;, and the rest of your Elixir code will live under &lt;code&gt;lib/my_app&lt;/code&gt;. This is the basic setup, and you can tweak it, and change it as much as you like. You have complete liberty as to how to organize your code.&lt;/p&gt;

&lt;p&gt;Since I started writing AlloyCI before Phoenix 1.3 was fully released, some of the folder structure is different than the one the latest 1.3 generators create. I prefer the way AlloyCI is structured right now, because I really don’t like the way they renamed the &lt;code&gt;web/&lt;/code&gt; folder to &lt;code&gt;alloy_ci_web/&lt;/code&gt; and everything inside it from &lt;code&gt;AlloyCi.Web.XXX&lt;/code&gt; to &lt;code&gt;AlloyCiWeb.XXX&lt;/code&gt;. I really prefer the separation in the module name, and the fact that the app name is not repeated in the web folder name. Thanks to the flexibility Phoenix provides, I don’t need to follow the conventions, though.&lt;/p&gt;

&lt;p&gt;Anyways, the most important part about the structure changes, is that Phoenix now guides you towards using contexts for structuring your data access layer.&lt;/p&gt;

&lt;p&gt;Using AlloyCI as an example, we have the &lt;code&gt;Accounts&lt;/code&gt; context (which is under &lt;code&gt;lib/alloy_ci/accounts&lt;/code&gt; folder), where the &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Authentication&lt;/code&gt;, and &lt;code&gt;Installation&lt;/code&gt; schemas live. These 3 schemas are closely related, and belong to the same business logic, namely the handling of Accounts.&lt;/p&gt;

&lt;p&gt;If you look closely at the files under the accounts folder, you will see that there are no functions in the schema files, other than the &lt;code&gt;changeset&lt;/code&gt; function. This means that I would need to either go straight through &lt;code&gt;Ecto&lt;/code&gt; to manipulate the database data (not recommended) or that I need an API boundary that will let me perform actions on the accounts related schemas.&lt;/p&gt;

&lt;p&gt;This is where the &lt;code&gt;AlloyCi.Accounts&lt;/code&gt; module comes into play. This module is the boundary with which AlloyCI will interact if it needs to perform an action on any of the schemas related to an Account. All public functions of this module provide an easy way to manipulate the data, while providing security through a layer of indirection.&lt;/p&gt;

&lt;p&gt;This is the purpose of contexts. They provide a boundary between your data layer and your business logic, and allow you to have an explicit contract that tells you how you can manipulate your data. It also allows you to stay independent from Ecto.&lt;br&gt;
Let’s say, in the future, you’d like to switch from Ecto to the “latest, coolestDB driver”. If you didn’t use an abstraction layer, like the contexts, you would have to refactor every function across the codebase that used Ecto to communicate to the data layer. But since we are using contexts, we would only need to refactor the code inside the context itself.&lt;/p&gt;
&lt;h2&gt;
  
  
  Data Presentation
&lt;/h2&gt;

&lt;p&gt;The code that will actually present your data to the user can live under the &lt;code&gt;lib/my_app/web&lt;/code&gt; or &lt;code&gt;lib/my_app_web&lt;/code&gt; folders, depending on how you want to structure it (the automatic generator will default to &lt;code&gt;lib/my_app_web&lt;/code&gt; but I prefer the former).&lt;/p&gt;

&lt;p&gt;In here you will find the folders where your controllers, views, templates and channels will live. Let’s start with the presentation layer.&lt;/p&gt;
&lt;h3&gt;
  
  
  Views &amp;amp; Templates
&lt;/h3&gt;

&lt;p&gt;If you come from a Rails background, you might wonder why there are two components to presenting the data, when in Rails all you need is the views folder. In Phoenix, the “views” are not composed of templated HTML files, but rather they are regular Elixir modules. These modules are there to help you share code with the template, and fulfill a similar purpose as the Rails “View Helpers”, but are, by default, specific to a single controller (other views are not loaded, unlike Rails that loads all view helpers, regardless of the controller being called). &lt;/p&gt;

&lt;p&gt;This separation makes it easier to use the same signature on similar helper functions needed to present data (without really overloading them), depending on which controller is being called, thus simplifying your code.&lt;/p&gt;

&lt;p&gt;The templates are, then, where your HTML code lives. The template files are saved as &lt;code&gt;*.html.eex&lt;/code&gt; files (meaning embedded Elixir), and are very similar to &lt;code&gt;erb&lt;/code&gt; files. The syntax is exactly the same, but instead of Ruby code inside, you write Elixir code 😄&lt;/p&gt;

&lt;p&gt;A very important distinction between Phoenix and Rails is how you share information between the controller and the template. In Rails, it is enough to declare an instance variable with &lt;code&gt;@something&lt;/code&gt; and it will be available to the template/view.&lt;br&gt;
Given the functional nature of Elixir, in Phoenix you need to explicitly pass the information you wish to be available to the views in the render function. These are called assigns. As an example, here is the &lt;code&gt;show&lt;/code&gt; action of the &lt;code&gt;PipelineController&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"project_id"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_claims&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Pipeline&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;Pipelines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;builds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Builds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;by_stage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"show.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;builds:&lt;/span&gt; &lt;span class="n"&gt;builds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;pipeline:&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;current_user:&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;conn&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;put_flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Project not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to:&lt;/span&gt; &lt;span class="n"&gt;project_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything that comes after "show.html" are the assigns, so the variables available to the templates related to the show action are &lt;code&gt;builds&lt;/code&gt;, &lt;code&gt;pipeline&lt;/code&gt;, and &lt;code&gt;current_user&lt;/code&gt;. We can see an example of how to use them in this snippet from the pipeline info header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"page-head"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"page-head-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;pipeline.project.owner&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;pipeline.project.name&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"breadcrumb"&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"navigation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Breadcrumb --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ol&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breadcrumb page-head-nav"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breadcrumb-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;ref_icon&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;pipeline.ref&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;clean_ref&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;pipeline.ref&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breadcrumb-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="err"&gt;("&lt;/span&gt;&lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="err"&gt;")&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;sha_link&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breadcrumb-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="err"&gt;("&lt;/span&gt;&lt;span class="na"&gt;book&lt;/span&gt;&lt;span class="err"&gt;")&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;pretty_commit&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;pipeline.commit&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="err"&gt;"])&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;pipeline.commit&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="na"&gt;pr_commit_message&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breadcrumb-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="err"&gt;("&lt;/span&gt;&lt;span class="na"&gt;code-fork&lt;/span&gt;&lt;span class="err"&gt;")&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;pipeline.commit&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="na"&gt;pr_commit_message&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"breadcrumb-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="err"&gt;("&lt;/span&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="err"&gt;")&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;String.capitalize&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;pipeline.status&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;status_icon&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="na"&gt;pipeline.status&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once a variable has been assigned, it is available to the template via &lt;code&gt;@var_name&lt;/code&gt;, just like with Rails. Functions defined in the view file of the same name as the controller (in this example &lt;code&gt;pipeline_view.ex&lt;/code&gt;) are immediately available to the template. In the above example, &lt;code&gt;sha_link/1&lt;/code&gt; creates an HTML link to the specific commit on GitHub.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controllers
&lt;/h3&gt;

&lt;p&gt;In structure, Phoenix Controllers are very similar to Rails Controllers, with the main difference being described above. When generated by the helper tools, they will have the same &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, and &lt;code&gt;delete&lt;/code&gt; actions as their Rails counterparts. And just as with Rails Controllers, you can define any action you desire by defining a function, and connecting a route to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Channels
&lt;/h3&gt;

&lt;p&gt;Phoenix Channels are used to communicate with the web client via Web Sockets. They are similar to ActionCable in Rails, but in my opinion, much more powerful, and performant. In AlloyCI, they are used to push the output of the build logs in real time, and to render a pre formatted piece of HTML code to show the user’s repositories (more on how AlloyCI uses Channels will be discussed in another post).&lt;/p&gt;

&lt;h3&gt;
  
  
  Routes
&lt;/h3&gt;

&lt;p&gt;Routes in Phoenix are defined in a somewhat similar way as Rails Routes. Some of the syntax is different, but it is immediately recognizable and feels familiar. Have a look at how the project routes are defined on AlloyCI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;AlloyCi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="s2"&gt;"/projects"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ProjectController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/pipelines"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PipelineController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/builds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BuildController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/artifact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BuildController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:artifact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="ss"&gt;:artifact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/artifact/keep"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BuildController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:keep_artifact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="ss"&gt;:keep_artifact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/badge/:ref"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BadgeController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:index&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real difference when it comes to routes, between Phoenix and Rails, is the power that you get when using plugs. We will discuss them in detail in a future post.&lt;/p&gt;




&lt;p&gt;And there you have it. That is the basic structure of a Phoenix project. There are other components that we haven’t covered here, like Plugs, or Background Jobs. We will discuss these advanced topics in a future blog post.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>opensource</category>
      <category>sideprojects</category>
      <category>devdiary</category>
    </item>
    <item>
      <title>On résumés and applying to jobs</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Fri, 02 Mar 2018 22:29:29 +0000</pubDate>
      <link>https://dev.to/suprnova32/on-rsums-and-applying-tojobs--4oha</link>
      <guid>https://dev.to/suprnova32/on-rsums-and-applying-tojobs--4oha</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1454165804606-c3d57bc86b40" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1454165804606-c3d57bc86b40"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve been thinking about writing this post for a while, specially after my short stint as a hiring manager for the Service Engineer position at GitLab. What finally notched me was this tweet by Stephanie Hurlburt where she asked her followers if they wanted their résumés reviewed. I realized it made sense to write some advice around this topic, and not just for résumés, but for applying to a job in general. So, let’s begin…&lt;/p&gt;




&lt;h3&gt;
  
  
  Keep it short
&lt;/h3&gt;

&lt;p&gt;While looking through resumes for the Service Engineer position at GitLab, I came across a high number of résumés that where more than 4 pages long.&lt;br&gt;
It is not necessary to list every single thing you have done in your résumé. List your most proud achievement first (if it’s relevant to the position), and follow up with the most recent positions you have held. Try to keep it single page, 2 pages at most. The people reviewing your résumé have a whole pile of them to go through. It helps if it’s short. I have seen profiles being discarded just because the résumé was too long, and they didn’t even give a glance to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailor your résumé to each position
&lt;/h3&gt;

&lt;p&gt;It is highly encouraged to tailor your résumé to the company and the position to which you are applying. This way you can showcase the particular skills you already have that match perfectly with the open position. List them first, or close to the top, and add information about projects on which you have worked that are relevant to the requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Personal information should be at the top
&lt;/h3&gt;

&lt;p&gt;Your personal information should be highly visible, preferably at the top of the document, and it should stand out. Use colors to highlight and contrast this information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Education should be further down
&lt;/h3&gt;

&lt;p&gt;Unless highly relevant to the position, education can go further down. It usually suffices to say the highest degree you have attained, no need to list specific courses and grades, unless, again, it’s highly relevant to the position. In this section you can also list the languages you speak, certificates you have attained, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add something interesting about yourself
&lt;/h3&gt;

&lt;p&gt;At the very end, add something interesting about yourself. Something that might let the hiring manager relate a bit to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use LaTeX, or InDesign for the layout
&lt;/h3&gt;

&lt;p&gt;Make your résumé shine! There are amazing résumé templates available that you can easily tailor to your needs, so you really outshine the competition. Word has gotten better in later versions, but it still cannot hold a candle to what you can do with LaTeX, or InDesign.&lt;/p&gt;

&lt;h3&gt;
  
  
  Always submit your résumé as a PDF
&lt;/h3&gt;

&lt;p&gt;PDF, PDF, PDF! It is called Portable Document File for something. It renders pretty much the same way on any machine. A Word, or other word processing document has its own weird way of rendering a document. It will most likely look different in my computer than it does on yours. I might not have the proper fonts, and the layout will get really screwed. This is a no-go. Always submit your résumé as a PDF.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your GitHub profile is not a résumé
&lt;/h3&gt;

&lt;p&gt;Having a lot of toy projects or tutorial projects on your GitHub profile and submitting that instead of a proper résumé will be detrimental to your application. These types of projects do not showcase your ability to work with other developers, or to grasp complex code, or that you actually have vast knowledge of the framework in which your toy projects are written.&lt;/p&gt;

&lt;p&gt;On the other hand, if you contribute to open source projects, in whatever form (documentation, issue triaging, helping people out on the issues or other forums, etc.) now this does showcase your ability to work with other developers, or to communicate complex subjects, or to prioritize. This kind of contributions can be more appealing to potential employers.&lt;/p&gt;

&lt;p&gt;Now I know there are great developers that are not able to contribute to open source. If that is the case for you, have some code samples of work that highlights your abilities, so that you can send to the technical interviewers upon request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use LinkedIn
&lt;/h3&gt;

&lt;p&gt;A lot of people seem to hate on LinkedIn, but it is a tool that is used by a lot of recruiters. Keep your profile updated, with your latest skills, your latest projects, your education, etc., and you might get job leads just for having a profile. A lot of recruiting software also allows you to pre-fill information on the application form from your LinkedIn profile, so it will save you some time.&lt;/p&gt;

&lt;p&gt;Keep it updated!&lt;/p&gt;




&lt;p&gt;After you have the perfect résumé, it is time to apply to the job opening, which it’s actually the most important part. No point on having the best résumé ever, if no one will see it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write a cover letter
&lt;/h3&gt;

&lt;p&gt;Nowadays most openings require you to write a cover letter, but even if they don’t, you should always submit one. This is your moment to shine! It is a freeform letter in which you get to tell them who you are in your own words. Put some thought into it, and take your time. A great cover letter can be more valuable that a résumé.&lt;br&gt;
Write about what makes you you, what inspires you, what excites you, and tailor it to each specific position. Showcase what you’ve done in a way that is relevant to the open position and makes you stand out.&lt;/p&gt;

&lt;h3&gt;
  
  
  If possible, have a personal blog
&lt;/h3&gt;

&lt;p&gt;Having a personal blog can only benefit you. It can show your ability explain complex topics in understandable ways, your communication skills, etc. It is also a great indicator that you will most likely be able to write good documentation.&lt;/p&gt;




&lt;p&gt;This is feedback that I have gather over the past 4 years of applying to different jobs, from my short stint as a hiring manager, and from watching other hiring managers at companies I’ve worked at. This is just my humble opinion, and should not be construed as professional advice, though. And with that I bid you good luck on the job hunt! 👍&lt;/p&gt;

</description>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>AlloyCI Dev Diary - Part 1</title>
      <dc:creator>Patricio Cano</dc:creator>
      <pubDate>Thu, 01 Mar 2018 17:11:03 +0000</pubDate>
      <link>https://dev.to/suprnova32/alloyci-dev-diary---part-1--1ai9</link>
      <guid>https://dev.to/suprnova32/alloyci-dev-diary---part-1--1ai9</guid>
      <description>&lt;h1&gt;
  
  
  Starting a new project
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1504917595217-d4dc5ebe6122%3Fixlib%3Drb-0.3.5%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26s%3De473b21e1b31fbf93ea6887690e1c3b1%26auto%3Dformat%26fit%3Dcrop%26w%3D3900%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1504917595217-d4dc5ebe6122%3Fixlib%3Drb-0.3.5%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26s%3De473b21e1b31fbf93ea6887690e1c3b1%26auto%3Dformat%26fit%3Dcrop%26w%3D3900%26q%3D80" alt="Photo by Christopher Burns on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going by AlloyCI’s &lt;a href="https://hackernoon.com/alloyci-dev-diary-part-1-8ae564fce9f3" rel="noopener noreferrer"&gt;introduction post&lt;/a&gt;, you would think that the idea to write a CI coordinator came pretty naturally for me, but it actually took me quite some time to find the perfect idea for a new project.&lt;/p&gt;

&lt;p&gt;Since the main purpose of starting this new project was to cement my newly acquired Elixir knowledge, I could have chosen something simpler, or even just gone along with the tutorial projects found in all language learning books. Something like a blog management system, a GitHub issue API client, a very simple CMS, etc. But I knew that if I went that route, I would stop adding features to the project as soon as I was done with the book. I did not want that to happen.&lt;/p&gt;

&lt;p&gt;I really think that a longer lived, more useful project, will have a more positive effect, than a one-off tutorial project, specially if you try to make something other people might find useful. But here’s the catch: Coming up with something other people might find useful is really hard!&lt;/p&gt;

&lt;p&gt;A good starting point is finding a problem that you might have that isn’t quite solved by current offerings. Chances are that more than one person out there has the same problem as you. Now, I’m not going to lie, it is going to take you a lot of time to come up with something usable, but that is part of the fun!&lt;/p&gt;

&lt;p&gt;I took me around 3 months until the CI coordinator idea creeped into my head. Before that I thought about re-implementing the omniauth-saml Ruby library in Elixir, but that idea quickly died when I realized that SAML support is almost non-existing in Erlang, let alone Elixir, at least nothing that can compare with ruby-saml and it’s power. Once that idea died, I continued with the re-implementing something idea for a while. I eventually gave up when I noticed that every idea I had to re-implement something, already had a corresponding Elixir project. In hindsight this might not have been the best idea. Even if there is already a library out there, you can always learn a lot by re-implementing it. Your own particular views and opinions can lead you to a better implementation of an existing solution. At the very least you will learn a lot.&lt;/p&gt;

&lt;p&gt;The idea to create the CI coordinator came to me, as many ideas often do, while I was in the shower. Clearing your mind and not thinking about a problem is often the best way to find a solution, I have experienced this multiple times in my life. Once the idea “presented itself”, I knew it had great potential. By re-implementing the GitLab CI API in Elixir I would be decoupling its system and liberating the GitLab Runner, making it compatible with other SCM systems. It would give new possibilities to an already great, but locked down project (the CI Runner). The last part was what really got me excited to get started. I could leverage an existing project to build something new, and simplify some of my approach, which would give me a head start, and make it possible to release an Alpha version quicker.&lt;/p&gt;

&lt;p&gt;The next day I got started with the basic project layout and did not go to bed until 4 am of the next day 😬&lt;/p&gt;

&lt;p&gt;And that is the squick story about how I got started with AlloyCI. Part 2 of the Dev Diary will be about project structure for a new Phoenix project, and the transition between 1.2 and 1.3 that AlloyCI went through before its public release.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>opensource</category>
      <category>sideprojects</category>
      <category>devdiary</category>
    </item>
  </channel>
</rss>
