<?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>Forem: Spiroman</title>
    <description>The latest articles on Forem by Spiroman (@spiroman).</description>
    <link>https://forem.com/spiroman</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%2F669420%2F275906ad-17da-4116-98f2-7da0381f532d.jpeg</url>
      <title>Forem: Spiroman</title>
      <link>https://forem.com/spiroman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/spiroman"/>
    <language>en</language>
    <item>
      <title>CircleCI - The Matrix</title>
      <dc:creator>Spiroman</dc:creator>
      <pubDate>Wed, 06 Oct 2021 16:23:23 +0000</pubDate>
      <link>https://forem.com/otomato_io/circleci-the-matrix-3c17</link>
      <guid>https://forem.com/otomato_io/circleci-the-matrix-3c17</guid>
      <description>&lt;h2&gt;
  
  
  Technical examples - &lt;a href="https://circleci.com/docs/2.0/configuration-reference/?utm_source=google&amp;amp;utm_medium=sem&amp;amp;utm_campaign=sem-google-dg--emea-en-dsa-maxConv-auth-brand&amp;amp;utm_term=g_b-_c__dsa_&amp;amp;utm_content=&amp;amp;gclid=Cj0KCQjwwNWKBhDAARIsAJ8HkhcOeFUi_qIiVpa0UfN44OT-KU3WyNBHAmYytRtA-ZP4mDkVngyIg5QaAsl8EALw_wcB#matrix-requires-version-21"&gt;The matrix&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This series of posts will focus on some tips and tricks that you can, and should implement in your config files. First, we will cover the matrix.&lt;/p&gt;

&lt;p&gt;This post assumes you have the basics down about circle CI configs, i.e: you know what: job, step, parameter, etc. mean. &lt;br&gt;
If you’re a complete beginner I would suggest you look up something beginner-friendly, that explains these topics (the official Circle documentation for example). I’m not saying this will be impossible to follow, but it is better if you get the full picture.&lt;/p&gt;

&lt;p&gt;For each topic, I will post links to official documentation where you can read all the technicalities. &lt;/p&gt;
&lt;h3&gt;
  
  
  Matrix basics
&lt;/h3&gt;

&lt;p&gt;The matrix is there to help you avoid repeating yourself, and run similar jobs that only differ from one another by a few lines.&lt;br&gt;
We will cover multiple configurations, building upon our first example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test-and-build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;service&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;svc1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;&amp;lt; parameters.service &amp;gt;&amp;gt;&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create 3 jobs that will run in parallel, and each will be passed a different value for the service parameter. I also included an example of such a job, where the first command accepts the service parameter. Now, you might ask yourself why would I need to do that?&lt;/p&gt;

&lt;p&gt;Here’s why (this is just one example out of many): let’s say that you are working with a monorepo that contains multiple services (or projects, depends on how you call them - I will call them services) and for each of them, before deploying, you would like to install dependencies, lint, test, and maybe “Dockerize”. &lt;/p&gt;

&lt;p&gt;Now, if you’re not doing this with a matrix, you can either copy and paste 3 jobs that only differ by the name of the service you’re currently doing all of the above for, or you’ve created a very long job that does all of that for each of them sequentially (please don’t do that). &lt;/p&gt;

&lt;p&gt;In contrast, if you’re using a matrix, you would only need to write one job that accepts as a parameter which service to work on. Moreover, when you expand and would like to test another service, all you would need to do is expand that list (service field in the matrix).&lt;/p&gt;

&lt;p&gt;Here’s what it would look like in a case you don’t use matrices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test-and-build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;test3&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc1"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step3&lt;/span&gt;
  &lt;span class="na"&gt;test2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc1"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step3&lt;/span&gt;
  &lt;span class="na"&gt;test3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;step1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;step3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This doesn’t look &lt;em&gt;terrible&lt;/em&gt;, yet. But it’s only because this is a basic example, and because we’re using our own commands (will cover in another post). The moment you need to test a new service, you will have to copy an entire such block. Same with when you would want to add a new step to your testing job, you will have to add it to every single one… It gets time consuming, trust me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi dimensional matrices
&lt;/h3&gt;

&lt;p&gt;Let’s expand our previous example and look at something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test-and-build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             
              &lt;span class="na"&gt;service&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;svc1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
              &lt;span class="na"&gt;os&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;linux"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;macos"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, all we’ve done is add another parameter to the matrix, but the implications are amazing. What will happen now, is that we will get 6 jobs (&lt;a href="https://en.wikipedia.org/wiki/Cartesian_product"&gt;Cartesian Product&lt;/a&gt; of parameters), and can now test each service on two different OS’s. No need to write the same job over and over. Pretty nifty eh?&lt;br&gt;
&lt;em&gt;Please note&lt;/em&gt; that your matricized job cannot expand into more than &lt;strong&gt;128 jobs&lt;/strong&gt;!&lt;/p&gt;
&lt;h3&gt;
  
  
  Dependencies between matricized jobs
&lt;/h3&gt;

&lt;p&gt;Continuing with our first example, we will look at two different ways to “wait” for these jobs to complete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test-and-build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-&amp;lt;&amp;lt; matrix.service &amp;gt;&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             
              &lt;span class="na"&gt;service&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;svc1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-&amp;lt;&amp;lt; matrix.service &amp;gt;&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-&amp;lt;&amp;lt; matrix.service &amp;gt;&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             
              &lt;span class="na"&gt;service&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;svc1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test-and-build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             
              &lt;span class="na"&gt;service&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;svc1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;requires&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;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             
              &lt;span class="na"&gt;service&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;svc1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s examine the differences between the two:&lt;/p&gt;

&lt;p&gt;In the first example, we’re assigning a name to each of the testing jobs i.e: “test-svc1”, “test-svc2”... Following that, each of our 3 build jobs will await for its corresponding test job to end. Meaning that “build-svc1” will wait for “test-svc1”, and so on. &lt;br&gt;
Please note that in order to wait for each job individually, you &lt;strong&gt;must name them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the second example, we’re waiting for all 3 of the &lt;strong&gt;test jobs&lt;/strong&gt; to be complete before starting our &lt;strong&gt;build jobs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Both ways are valid, and it’s up to you to decide which one you need (In some cases, a composition of the two methods could be needed).&lt;/p&gt;
&lt;h3&gt;
  
  
  Anchors and aliases
&lt;/h3&gt;

&lt;p&gt;One last thing I want to cover is anchors and aliases. Let’s see how we can modify one of the previous examples to avoid repeating ourselves too much:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test-and-build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-&amp;lt;&amp;lt; matrix.service &amp;gt;&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;params&lt;/span&gt;            
              &lt;span class="na"&gt;service&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;svc1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;svc3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-&amp;lt;&amp;lt; matrix.service &amp;gt;&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-&amp;lt;&amp;lt; matrix.service &amp;gt;&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             
              &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*params&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can guess, this will function similarly to our previous example. The only difference is that we don’t have to add another service to all the jobs that use the service parameter. We’ll only need to add new services to the first map, after which all the other references will have the modified map as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;This is the second post of the series which deals with the matrix. Read the other posts to see more technical examples.&lt;br&gt;
Cheers!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Battle-tested CircleCI tips and tricks</title>
      <dc:creator>Spiroman</dc:creator>
      <pubDate>Wed, 06 Oct 2021 16:11:38 +0000</pubDate>
      <link>https://forem.com/otomato_io/battle-tested-circleci-tips-and-tricks-3n68</link>
      <guid>https://forem.com/otomato_io/battle-tested-circleci-tips-and-tricks-3n68</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Hello, everyone! &lt;br&gt;
In this series of posts, I will cover a variety of topics that I think everyone who works with CircleCI (Circle) should know. For all the posts in this series, I’m assuming that the reader is familiar with the general concepts of Circle. If you’re not - I suggest you read up on such concepts as &lt;a href="https://circleci.com/docs/2.0/configuration-reference/#workflows" rel="noopener noreferrer"&gt;workflow&lt;/a&gt;, &lt;a href="https://circleci.com/docs/2.0/configuration-reference/#jobs" rel="noopener noreferrer"&gt;job&lt;/a&gt;, step, &lt;a href="https://circleci.com/docs/2.0/configuration-reference/#commands-requires-version-21" rel="noopener noreferrer"&gt;command&lt;/a&gt;, and other basic terms.&lt;br&gt;
You could still follow along, but some things might not be clear right off the bat.&lt;/p&gt;

&lt;h3&gt;
  
  
  Circle CI config structure
&lt;/h3&gt;

&lt;p&gt;First, we’ll talk about the structure of your config file (AKA the CircleCI YAML). It should look something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45za661o6x83eir8siv3.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45za661o6x83eir8siv3.jpeg" alt="Diagram of config structure"&gt;&lt;/a&gt;&lt;br&gt;
Where each part of the Config file signifies the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Config - This part will specify the version of your CircleCI config. Any Orbs, and their versions (I’ll talk about orbs later), and any parameters you wish to define “CI wide”&lt;/li&gt;
&lt;li&gt;Workflow - The main component of every Circle config, this is our entry point where we define workflows (there can be multiple; nightly, tests, etc). Each workflow is composed of multiple &lt;strong&gt;jobs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Jobs - A series of steps/commands that will be executed on a specified machine. You can write out your own steps, or use predefined commands.&lt;/li&gt;
&lt;li&gt;Commands - Those are steps that you have previously defined and will reference in your jobs. They are responsible for the actual work, they will have your shell commands that you wish to execute. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have ordered them in this specific order to make it easier to read and understand what’s going on (you’re free to order them as you like). &lt;/p&gt;

&lt;p&gt;The first thing you want to see is your configs for the run in order to see which &lt;strong&gt;orbs&lt;/strong&gt; are present and what parameters are defined.&lt;br&gt;
Next, the &lt;strong&gt;workflows&lt;/strong&gt;. Your first level of abstraction. Just from the name you will see what their purpose is and what jobs they run.&lt;br&gt;
&lt;strong&gt;Jobs&lt;/strong&gt; are your second level of abstraction, they’ll have the actual &lt;strong&gt;commands&lt;/strong&gt;, and you’ll be able to see what’s executed and in what order.&lt;br&gt;
Lastly, the &lt;strong&gt;commands&lt;/strong&gt;. There’s no abstraction here, this is the actual stuff that gets run (test, compile, build, push, etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  Orbs
&lt;/h3&gt;

&lt;p&gt;Orbs are another thing I want to talk about. They are:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“shareable packages of CircleCI configuration you can use to simplify your builds” - CircleCI. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I strongly suggest that before you start writing your own steps inside any job you look at what’s available online. Usually, someone already encountered the same problem you’re having and made things easier by writing an orb that you can use in your own config.&lt;br&gt;
    If you’re not sure what I mean by that, here’s an example: you want to build a Docker container and upload it to ECR (AWSs’ container registry). Instead of manually installing the AWS CLI on your machine and setting up your profile and writing all the commands yourself, you can use &lt;a href="https://circleci.com/developer/orbs/orb/circleci/aws-cli" rel="noopener noreferrer"&gt;their orb&lt;/a&gt; that does all that for you! Amazing, I know.&lt;br&gt;
    There are many more use cases: Slack messaging, installing Node, Golang, etc. Go explore them yourselves.&lt;br&gt;
    &lt;em&gt;Please note&lt;/em&gt; that they may not always fit exactly what you need! In some cases, it's easier to write out the steps manually than use some limited functionality that an orb offers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secrets
&lt;/h3&gt;

&lt;p&gt;Secrets! You will inevitably want to use some secret information that &lt;strong&gt;shouldn't be written as plain text&lt;/strong&gt; in your config file, this is where secrets come in. There are two types: organization, or project. Organization secrets are accessible from all projects/repos, while project-type secrets are only accessible from within the project/repo in which they are defined.&lt;br&gt;
Their names are not actually secrets, but rather: &lt;em&gt;Context&lt;/em&gt;, and &lt;em&gt;Environment Variables&lt;/em&gt;, respectively. You can check out how to define contexts &lt;a href="https://circleci.com/docs/2.0/contexts/#creating-and-using-a-context" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and env vars &lt;a href="https://circleci.com/docs/2.0/contexts/#environment-variable-usage" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
    Now, the question that comes to mind is when should I define a context secret, rather than an environment variable? Before I answer that, I want to clarify something about contexts, they are not exactly key-value pairs like environment variables are, but rather a &lt;strong&gt;collection of key-value pairs&lt;/strong&gt;.&lt;br&gt;
    With this in mind, I can tell you my general rule of thumb for deciding which one to use. A collection of secrets, that serve the same purpose, or are going to be needed organization-wide, should be put in one context; e.g, a context named aws-access will hold: access keys, account Id, region, URLs, etc. While one-off project-specific secrets should be placed in an environment variable. &lt;/p&gt;

&lt;p&gt;Here's a flowchart to get you started:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gfhnj3ier2tyb84awfe.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gfhnj3ier2tyb84awfe.jpeg" alt="Secret creation flowchart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will save you a lot of time if, for example, you change access keys. If you define them in a context, all you need to update is one or two fields, while if you define them as an environment variable, you will have to go from project to project updating those two values.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;This is the first post of the series which deals with more "&lt;em&gt;philosophical&lt;/em&gt;" topics. Read the next posts to see more technical examples.&lt;br&gt;
Cheers!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>tutorial</category>
      <category>circleci</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
