<?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: Sebastian Linares L.</title>
    <description>The latest articles on DEV Community by Sebastian Linares L. (@sebalinares).</description>
    <link>https://dev.to/sebalinares</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%2F172071%2F45b718c1-197b-40ed-9cc5-5283d2d35f98.png</url>
      <title>DEV Community: Sebastian Linares L.</title>
      <link>https://dev.to/sebalinares</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sebalinares"/>
    <language>en</language>
    <item>
      <title>Profesionaliza tus proyectos personales con CircleCI + Netlify + Github Parte 2</title>
      <dc:creator>Sebastian Linares L.</dc:creator>
      <pubDate>Tue, 12 Nov 2019 01:44:27 +0000</pubDate>
      <link>https://dev.to/sebalinares/profesionaliza-tus-proyectos-personales-con-circleci-netlify-github-parte-2-4j2f</link>
      <guid>https://dev.to/sebalinares/profesionaliza-tus-proyectos-personales-con-circleci-netlify-github-parte-2-4j2f</guid>
      <description>&lt;p&gt;Está es la continuación de mi post &lt;a href="https://dev.to/sebalinares/upgrading-your-personal-project-game-with-circleci-circleci-netlify-github-part-1-eng-5bp2"&gt;post anterior&lt;/a&gt;. Concluiremos esta serie con la implementación del CD en CI/CD - Continuous Delivery. &lt;/p&gt;

&lt;h2&gt;
  
  
  Resultado 🔚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Un proyecto alojado en Netlify (free tier)&lt;/li&gt;
&lt;li&gt;Un nuevo archivo de configuración CircleCI &lt;code&gt;config.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Un flujo de trabajo en CircleCI que nos permitirá hacer &lt;em&gt;deploy&lt;/em&gt; cada vez que hagamos &lt;em&gt;merge&lt;/em&gt; a un pull request de nuestra &lt;code&gt;master branch&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Continuous Delivery (CD) 🤝
&lt;/h2&gt;

&lt;p&gt;En esta edición no recurriré a la documentación de Microsoft, si no que a la de &lt;a href="//www.continuousdelivery.com"&gt;continuousdelivery.com&lt;/a&gt;, que dice: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Continuous Delivery es la habilidad de obtener los cambios de todo tipo, incluyendo las nuevas características, cambios de configuración, bug fixes y experimentos, a producción o a las manos de los usuarios, de una manera segura, rápida y sostenible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Una definición bastante completa. En el último post, hablamos acerca de la integración. Una instancia para un testing completo - nos gustaría -, el último checkeo para estar seguros que los cambios que hicimos a nuestra aplicación no romperán el producto final. Ahora - en el continuous delivery -, es tiempo de asegurar que nuestro usuario final reciba la aplicación de la manera más rápida e integra🏃‍♂️.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/l0IykI5OLMhjtnB60/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l0IykI5OLMhjtnB60/giphy.gif" alt="like-a-boss"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Primer paso 1️⃣: Crear una cuenta en Netlify
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Entramos &lt;a href="https://app.netlify.com/signup/email"&gt;este link&lt;/a&gt; y creamos una cuenta.&lt;/li&gt;
&lt;li&gt;Una vez que terminemos de registrarnos, seremos redirigidos a nuestro panel de control, el cual estará vacío. Hacemos click en &lt;em&gt;New site from Git&lt;/em&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LWr2MC7O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/new-site.jpg" alt="new-site"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click en Github e ingresamos nuestras credenciales 🔐&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hW_YfVis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-credentials.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hW_YfVis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-credentials.jpg" alt="github-credentials"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aparecerá una solicitud de instalación 🔧 que necesita hacerse en Github &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tenemos dos opciones aquí: permitir que Netlify tenga acceso a todos nuestros proyectos o solamente a los que escojamos. Elegiremos la última y solo permitiremos que Netlify vea la aplicación que creamos en el último post.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5EybQqks--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/install-netlify.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5EybQqks--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/install-netlify.jpg" alt="install-netlify"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hacemos click en &lt;code&gt;Install&lt;/code&gt; e ingresamos nuestra clave 🔑 .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;En la ventana siguiente, hacemos click nuevamente en el nombre de nuestro proyecto de Github&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ahora veremos un formulario donde podemos configurar nuestras &lt;em&gt;build options&lt;/em&gt; para el proyecto. Lo dejaremos como está, porque así tal cual es como lo necesitamos para los siguientes pasos.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LZmfdAyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/deploy-settings.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LZmfdAyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/deploy-settings.jpg" alt="deploy-settings.jpg"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hagamos click en &lt;em&gt;Deploy Site&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Si están siguiendo esta serie de posts, todo debería funcional y en un par de segundos su proyecto deberá haberse generado. Abajo del nombre de su proyecto, debería haber un link con una extensión &lt;code&gt;.netlify.com&lt;/code&gt;. Si le hacemos click seremos redirigidos a nuestro nuevo sitio web!&lt;br&gt;
&lt;a href="https://i.giphy.com/media/3ohzdIuqJoo8QdKlnW/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3ohzdIuqJoo8QdKlnW/giphy.gif" alt="awesome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si el sitio no fue creado 🙅🏽‍♂️, sugiero estos posibles escenarios.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Su proyecto fue creado con NPM y en el 8vo paso, lo configuramos para usarse con &lt;code&gt;yarn build&lt;/code&gt;. Solo tenemos que ir a &lt;code&gt;settings &amp;gt; build &amp;amp; deploy &amp;gt; edit settings&lt;/code&gt;. Ahí podremos modificar nuestro &lt;code&gt;build command&lt;/code&gt; para usar NPM.&lt;/li&gt;
&lt;li&gt;Quizás a Netlify le dimos permisos para otro repositorio. Para revisar que repositorio está conectado con nuestra cuenta Netlify, vayamos a &lt;code&gt;setting&lt;/code&gt; y abajo de la url, hacemos click donde dice &lt;code&gt;Github&lt;/code&gt;. Ese link nos redireccionara al repositorio en conexión. &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Agregar un build Hook a nuestra configuración de Netlify
&lt;/h2&gt;

&lt;p&gt;En simples palabras, el build hook &lt;strong&gt;es un endpoint&lt;/strong&gt;. Si enviamos un &lt;code&gt;POST&lt;/code&gt; request vacío, desencadenaríamos el proceso de &lt;code&gt;build&lt;/code&gt; + &lt;code&gt;deploy&lt;/code&gt; de la rama master de nuestro repositorio.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/5xaOcLE3ZnWJhT2IYCY/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/5xaOcLE3ZnWJhT2IYCY/giphy.gif" alt="unleash-the-beast-gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Vayamos a &lt;code&gt;settings &amp;gt; build &amp;amp; deploy&lt;/code&gt; y bajemos hasta &lt;code&gt;build hooks&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c_ivctgk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c_ivctgk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-1.jpg" alt="build-hook-1"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hacemos click en &lt;code&gt;Add build Hook&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0AIihw0w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0AIihw0w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-2.jpg" alt="build-hook-2"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Le asignamos un nombre descriptivo y guardamos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copíamos la url que se generó. Peguémosla en algún lugar porque la necesitaremos más tarde.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oOzmjxNd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-end.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oOzmjxNd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-end.jpg" alt="build-hook-end"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Configurar una environment variable en CircleCI
&lt;/h2&gt;

&lt;p&gt;Ya tenemos una url que sirve como un endpoint para desencadenar nuestro &lt;em&gt;build + deploy&lt;/em&gt;. Ahora vamos a usar eso en nuestro archivo de configuración de CircleCI &lt;code&gt;config.yml&lt;/code&gt;. Pero como buenos desarrolladores que somos, me imagino que no queremos que esa &lt;code&gt;url&lt;/code&gt; quedé pública en nuestro repositorio de Github 🤔 - cualquiera podría gatillar un deploy simplemente enviando un POST a esa url. Para esto, tenemos variables de ambiente que los amables trabajadores de CircleCi nos han provisto.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vayamos a nuestra app de CircleCI&lt;/li&gt;
&lt;li&gt;Hacemos click en &lt;code&gt;Jobs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hagamos click en el ícono de configuración que está al lado del nombre de nuestro proyecto&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--48bX16Xs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/job-settings.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--48bX16Xs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/job-settings.jpg" alt="job-settings"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nos encontramos dentro de la configuración específica para ese &lt;code&gt;Job&lt;/code&gt;. Hacemos click donde dice &lt;code&gt;Environment Variables&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ahora click en &lt;code&gt;Add Variable&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qwhwXwSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/environment-variables-circleci.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qwhwXwSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/environment-variables-circleci.jpg" alt="environment-variables-circleci"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Le daremos un nombre descriptivo - &lt;code&gt;awesome_endpoint&lt;/code&gt; -, y en el &lt;code&gt;value&lt;/code&gt; pegamos el endpoint que guardamos anteriormente - la url del build hook de netlify&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hagamos click en &lt;code&gt;Add Variable&lt;/code&gt; nuevamente&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hIKVOx21--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/add-environment-variable.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hIKVOx21--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/add-environment-variable.jpg" alt="add-environment-variable"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Casi listos, solo un paso más!&lt;/p&gt;
&lt;h2&gt;
  
  
  Cambiar la configuración de CircleCI
&lt;/h2&gt;

&lt;p&gt;En nuestro último archivo &lt;code&gt;config.yml&lt;/code&gt; solo ejecutamos un set de test. Ahora el objectivo es testear solo en nuestra &lt;code&gt;feature branch&lt;/code&gt; y únicamente hacer &lt;code&gt;deploy&lt;/code&gt; cuando hacemos &lt;em&gt;merge&lt;/em&gt; de una &lt;em&gt;pull request&lt;/em&gt; hacia nuestra rama master.&lt;/p&gt;

&lt;p&gt;PRIMERO: Asegurémonos de estar en la &lt;code&gt;feature branch&lt;/code&gt;, no en la &lt;code&gt;master&lt;/code&gt; 🙏🏽. Si vemos el archivo &lt;code&gt;config.yml&lt;/code&gt;, veremos la palabra &lt;code&gt;jobs&lt;/code&gt;. Abajo de esto, solo veremos un &lt;code&gt;job&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;. Ahora agregaremos un segundo job, lo llamaremos &lt;code&gt;deploy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;En este &lt;code&gt;job&lt;/code&gt; especificaremos en qué máquina queremos trabajar. En este caso elijamos una &lt;code&gt;macos&lt;/code&gt;. Luego recuerdan la url que nos dieron en nuestro &lt;code&gt;build hook&lt;/code&gt; 🧠, la usaremos nuevamente. &lt;/p&gt;

&lt;p&gt;Su nuevo &lt;code&gt;job&lt;/code&gt; debería verse así.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;macos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;xcode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;9.0'&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;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -X POST -d {} ${awesome_endpoint}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Cómo pueden imaginar, detrás de &lt;code&gt;${awesome_endpoint}&lt;/code&gt; se esconde nuestra variable de ambiente con el endpoint secreto que gatilla el &lt;em&gt;build + deploy&lt;/em&gt; del proyecto. &lt;/p&gt;

&lt;p&gt;Ahora tenemos dos &lt;code&gt;jobs&lt;/code&gt;, build &amp;amp; deploy. Como los unimos? Con &lt;code&gt;workflows&lt;/code&gt;. Podemos agendar los &lt;code&gt;jobs&lt;/code&gt; que queremos que se gatillen ante ciertas condiciones que previamente configuraremos. Más información &lt;a href="https://circleci.com/docs/2.0/workflows/"&gt;aquí en la documentación&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&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;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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Primero, declaramos la palabra clave &lt;code&gt;workflows&lt;/code&gt;. Luego, escribimos cada &lt;code&gt;job&lt;/code&gt; que queremos ejecutar y filtramos cada uno por &lt;code&gt;branches&lt;/code&gt;. El &lt;code&gt;build&lt;/code&gt; job ignora la &lt;code&gt;master branch&lt;/code&gt;, por lo tanto se ejecuta en cualquier otra rama. Por otro lado, el job &lt;code&gt;deploy&lt;/code&gt; estipula que se ejecutará &lt;strong&gt;solo&lt;/strong&gt; en la rama &lt;code&gt;master&lt;/code&gt;. Tal como lo hablamos anteriormente, estamos pensando en hacer el testing en la &lt;code&gt;feature branch&lt;/code&gt; y luego solo hacer &lt;code&gt;deploy&lt;/code&gt; en &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nuestro archivo final &lt;code&gt;config.yml&lt;/code&gt; debería terminar viéndose así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&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;circleci/node:lts&lt;/span&gt;
    &lt;span class="na"&gt;working_directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/repo&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="s"&gt;checkout&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;restore_cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;save_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;node_modules&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;macos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;xcode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;9.0'&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;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -X POST -d {} ${awesome_endpoint}&lt;/span&gt;


&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&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;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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Hacer commit de los cambios y push a la feature branch
&lt;/h2&gt;

&lt;p&gt;El único cambio que hicimos en el código del repositorio fue en el archivo &lt;code&gt;config.yml&lt;/code&gt;. Lo agregamos y hacemos push a nuestro remoto con &lt;code&gt;git add .circleci/config.yml &amp;amp;&amp;amp; git commit -m 'circleci: add deploy job and workflow' &amp;amp;&amp;amp; git push origin &amp;lt;branch_name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Creamos un pull request como vimos en el post anterior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ahora se ven los resultados de todo lo que hemos hecho en los últimos dos posts.
&lt;/h3&gt;

&lt;p&gt;Primero, tenemos que esperar que los &lt;em&gt;checks&lt;/em&gt; se completen. Específicamente el job &lt;code&gt;build&lt;/code&gt; que es el que configuramos en nuestra &lt;code&gt;master branch&lt;/code&gt; como protección. Si no se completa exitosamente, no podremos hacer *&lt;em&gt;merge&lt;/em&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qGeh5HvU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-merging.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qGeh5HvU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-merging.jpg" alt="github-merging"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Mientras esperamos, en CircleCI nuestro &lt;code&gt;build&lt;/code&gt; esta corriendo&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yTZkbHen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/feature-branch-circleci-job-success.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yTZkbHen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/feature-branch-circleci-job-success.jpg" alt="feature-branch-circleci-job-success"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Luego de haber hecho &lt;em&gt;merge&lt;/em&gt; del pull request, el job &lt;code&gt;deploy&lt;/code&gt; se ejecuta en nuestra &lt;code&gt;master branch&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Of_f_D7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/master-branch-circleci-build-running.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Of_f_D7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/master-branch-circleci-build-running.jpg" alt="master-branch-circleci-build-running"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Cuando se completa, se gatilla el &lt;code&gt;build hook&lt;/code&gt; de Netlify - el que declaramos en la variable de ambiente de CircleCI. Esto gatilla un build + deploy en nuestro sitio de Netlify - el con la &lt;code&gt;.netlify.com&lt;/code&gt; extension.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E2sz3oaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-building-in-process.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E2sz3oaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-building-in-process.jpg" alt="netlify-building-in-process"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Finalmente, luego de que la &lt;em&gt;build&lt;/em&gt; de Netlify es exitosa, nuestro sitio web está listo!&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ywH26QLM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-deploy-success.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ywH26QLM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-deploy-success.jpg" alt="netlify-deploy-success"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DONE&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/DffShiJ47fPqM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/DffShiJ47fPqM/giphy.gif" alt="yes!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Últimas palabras
&lt;/h2&gt;

&lt;p&gt;Esto concluye nuestro viaje. Ahora son los modestos dueños de un proyecto que hace testing y deploy automático. Siéntanse orgullosos y pueden hacerle el &lt;code&gt;overkill&lt;/code&gt; que quieran con lo aprendido, hasta a sus proyecto más sencillos. Crean en sus proyectos, son geniales.&lt;/p&gt;

&lt;p&gt;Saludos!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/gdkVL0ljDHbNcXQOZD/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/gdkVL0ljDHbNcXQOZD/giphy.gif" alt="self-claps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Más información
&lt;/h2&gt;

&lt;p&gt;La &lt;a href="https://circleci.com/docs/"&gt;documentación de CircleCI&lt;/a&gt; puede darles un mayor entendimiento de cómo usar la plataforma.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cicd</category>
      <category>github</category>
      <category>translate</category>
    </item>
    <item>
      <title>Upgrading Your Personal Project Game With  CircleCi + Netlify + Github - Part 2
</title>
      <dc:creator>Sebastian Linares L.</dc:creator>
      <pubDate>Wed, 06 Nov 2019 02:22:20 +0000</pubDate>
      <link>https://dev.to/sebalinares/upgrading-your-personal-project-game-with-circleci-netlify-github-part-2-4k8e</link>
      <guid>https://dev.to/sebalinares/upgrading-your-personal-project-game-with-circleci-netlify-github-part-2-4k8e</guid>
      <description>&lt;p&gt;This is the continuation of my &lt;a href="https://dev.to/sebalinares/upgrading-your-personal-project-game-with-circleci-circleci-netlify-github-part-1-eng-5bp2"&gt;last post&lt;/a&gt; on this series about &lt;em&gt;upgrading your personal project game&lt;/em&gt;. In this edition, we'll finish implementing the CD in CI/CD - continuous delivery. &lt;/p&gt;

&lt;h2&gt;
  
  
  End result 🔚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A project hosted on Netlify (free tier)&lt;/li&gt;
&lt;li&gt;A new &lt;code&gt;config.yml&lt;/code&gt; CircleCI configuration file.&lt;/li&gt;
&lt;li&gt;A workflow on CircleCI that will allow you to deploy on every merge of a pull request to your &lt;code&gt;master branch&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Continuous Delivery (CD) 🤝
&lt;/h2&gt;

&lt;p&gt;In this edition I'm not resorting to Microsoft docs, but to &lt;a href="//www.continuousdelivery.com"&gt;continuousdelivery.com&lt;/a&gt;, which says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Continuous Delivery is the ability to get changes of all types—including new features, configuration changes, bug fixes, and experiments—into production, or into the hands of users, safely and quickly in a sustainable way.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pretty straightforward. In the last post, we talked about the integration, an instance for thorough testing - you wish -, the last revision to be sure that the changes you just made to your app won't break the end product that the user receives. Now it's all about ensuring that your user gets that new app in the quickest and seamlessly way 🏃‍♂️.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/l0IykI5OLMhjtnB60/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l0IykI5OLMhjtnB60/giphy.gif" alt="like-a-boss"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  First Step 1️⃣: Create a Netlify account
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Enter &lt;a href="https://app.netlify.com/signup/email"&gt;this link&lt;/a&gt; and create an account.&lt;/li&gt;
&lt;li&gt;When you finish registering you'll be redirected to your dashboard, which will be empty. Click in "New site from Git".
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LWr2MC7O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/new-site.jpg" alt="new-site"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on Github and enter your credentials 🔐.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hW_YfVis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-credentials.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hW_YfVis--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-credentials.jpg" alt="github-credentials"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You'll be prompted with a Netlify installation 🔧 that needs to be done on Github. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have two options here, allow Netlify app to peak in all your projects or only on the selected ones. I'll choose the latter, only allow it on the project that we created in the last post.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5EybQqks--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/install-netlify.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5EybQqks--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/install-netlify.jpg" alt="install-netlify"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click install and write your password 🔑 .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the next window click again in the name of your Github Project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now you get to a form where you can set the build options of your repository. I'll leave this as it is because it is just how I need it to be for the next steps.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LZmfdAyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/deploy-settings.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LZmfdAyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/deploy-settings.jpg" alt="deploy-settings.jpg"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click in &lt;em&gt;Deploy Site&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are following this series everything should work and in a phew seconds your project should have built. Below your projects name, there should be a link with a &lt;code&gt;.netlify.com&lt;/code&gt; extension. If you click it, you will be redirected to your live website!&lt;br&gt;
&lt;a href="https://i.giphy.com/media/3ohzdIuqJoo8QdKlnW/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3ohzdIuqJoo8QdKlnW/giphy.gif" alt="awesome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your site wasn't deployed 🙅🏽‍♂️ I have some guesses in what could have happened :  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your project was built with npm and in the 8th step it was set to use &lt;code&gt;yarn build&lt;/code&gt;. You just need to go to &lt;code&gt;settings &amp;gt; build &amp;amp; deploy &amp;gt; edit settings&lt;/code&gt;. There you can modify your &lt;code&gt;build command&lt;/code&gt; to use npm.&lt;/li&gt;
&lt;li&gt;Maybe you gave Netlify permission to another repository. To check which repository your Netlify project is linked to, go to &lt;code&gt;setting&lt;/code&gt; and click below your app url where it says &lt;code&gt;Github&lt;/code&gt;. That link will redirect you to the repository of this particular build.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Add a build Hook to your Netlify configuration
&lt;/h2&gt;

&lt;p&gt;In simple words, the build hook is an endpoint. If you send an empty &lt;code&gt;POST&lt;/code&gt; request to it, you unleash a build + deploy of the target branch - master in this case.&lt;br&gt;&lt;br&gt;
&lt;a href="https://i.giphy.com/media/5xaOcLE3ZnWJhT2IYCY/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/5xaOcLE3ZnWJhT2IYCY/giphy.gif" alt="unleash-the-beast-gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;code&gt;settings &amp;gt; build &amp;amp; deploy&lt;/code&gt; and scroll down to &lt;code&gt;build hooks&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c_ivctgk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c_ivctgk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-1.jpg" alt="build-hook-1"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click in &lt;code&gt;Add build Hook&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0AIihw0w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0AIihw0w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-2.jpg" alt="build-hook-2"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write a descriptive name to your build and save it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the url that was generated on save. Paste it somewhere because we'll need it later.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oOzmjxNd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-end.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oOzmjxNd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/build-hook-end.jpg" alt="build-hook-end"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Configure an environment variable in CircleCI
&lt;/h2&gt;

&lt;p&gt;So now we have a url that serves us as an endpoint to trigger our build + deploy. We are going to use it in our CircleCi configuration file &lt;code&gt;config.yml&lt;/code&gt;. But as the good developers that you are, I imagine you don't want to put that same &lt;code&gt;url&lt;/code&gt; in the public github repository &lt;code&gt;config.yml&lt;/code&gt; file, no? 🤔 For that, we are going to use the environment variables that the people from CircleCI were kind enough to provide us. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your CircleCI app.&lt;/li&gt;
&lt;li&gt;Click in &lt;code&gt;Jobs&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click in the settings icon next to your project's name.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--48bX16Xs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/job-settings.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--48bX16Xs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/job-settings.jpg" alt="job-settings"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We entered the settings of that specific &lt;code&gt;Job&lt;/code&gt;. Click where it says &lt;code&gt;Environment Variables&lt;/code&gt;.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click in &lt;code&gt;Add Variable&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qwhwXwSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/environment-variables-circleci.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qwhwXwSo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/environment-variables-circleci.jpg" alt="environment-variables-circleci"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We'll give it a descriptive name like &lt;code&gt;awesome_endpoint&lt;/code&gt; and in the &lt;code&gt;value&lt;/code&gt; paste that endpoint url I told you to save previously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click in &lt;code&gt;Add Variable&lt;/code&gt; again.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hIKVOx21--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/add-environment-variable.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hIKVOx21--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/add-environment-variable.jpg" alt="add-environment-variable"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Almost done, one step more!&lt;/p&gt;
&lt;h2&gt;
  
  
  Change CircleCI configuration
&lt;/h2&gt;

&lt;p&gt;In our last &lt;code&gt;config.yml&lt;/code&gt; file we only ran a set of tests. Now the goals are to test only in your &lt;code&gt;feature branch&lt;/code&gt; and only deploy when your master branch merges a &lt;code&gt;pull request&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;FIRST: be sure to be in a &lt;code&gt;feature branch&lt;/code&gt;, NOT your &lt;code&gt;master&lt;/code&gt; 🙏🏽. If you look at the &lt;code&gt;config.yml&lt;/code&gt; file. You'll see the word &lt;code&gt;jobs&lt;/code&gt;. Below this, we can only see one &lt;code&gt;job&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;. We are going to add a second job, we'll name it &lt;code&gt;deploy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this &lt;code&gt;job&lt;/code&gt; we'll specify a machine to work on, in this case I chose a &lt;code&gt;macos&lt;/code&gt; one. Then, remember the url we were given in our &lt;code&gt;build hook&lt;/code&gt; 🧠, now it's time to use it - think it this way: Netlify calls the specified &lt;code&gt;command&lt;/code&gt; in an environment that runs a &lt;code&gt;macos&lt;/code&gt; virtual machine. &lt;/p&gt;

&lt;p&gt;Your new job will look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;macos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;xcode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;9.0'&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;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -X POST -d {} ${awesome_endpoint}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you imagine, behind that &lt;code&gt;${awesome_endpoint}&lt;/code&gt; hides the environment variable with the secret endpoint that triggers our project 👀. &lt;/p&gt;

&lt;p&gt;Now we have two CircleCi &lt;code&gt;jobs&lt;/code&gt;, build &amp;amp; deploy. How to join them? With &lt;code&gt;workflows&lt;/code&gt;. We can schedule jobs to run in certain conditions we previously configured. More information &lt;a href="https://circleci.com/docs/2.0/workflows/"&gt;here in the docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&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;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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First, we declare at top-level the &lt;code&gt;workflows&lt;/code&gt; keyword. Then, we write each job we want to run and filter each one by &lt;code&gt;branches&lt;/code&gt;. The &lt;code&gt;build&lt;/code&gt; job ignores master branch, so it runs on any other branch - very useful if our &lt;code&gt;feature branches&lt;/code&gt; will have various names. On the other hand, the &lt;code&gt;deploy&lt;/code&gt; job clearly stipulates that it will run &lt;strong&gt;only&lt;/strong&gt; in the &lt;code&gt;master&lt;/code&gt; branch. Like we talked before, we are only thinking in a suite of tests in our feature branch before merging and only deploy our &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;Your final &lt;code&gt;config.yml&lt;/code&gt; should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&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;circleci/node:lts&lt;/span&gt;
    &lt;span class="na"&gt;working_directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/repo&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="s"&gt;checkout&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;restore_cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;save_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;node_modules&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;machine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;macos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;xcode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;9.0'&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;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -X POST -d {} ${awesome_endpoint}&lt;/span&gt;


&lt;span class="na"&gt;workflows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&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;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;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;only&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Commit changes and push the feature branch
&lt;/h2&gt;

&lt;p&gt;The only changes we did in this repository's code was in the &lt;code&gt;config.yml&lt;/code&gt; file. Add it and push it to your remote repository with &lt;code&gt;git add .circleci/config.yml &amp;amp;&amp;amp; git commit -m 'circleci: add deploy job and workflow' &amp;amp;&amp;amp; git push origin &amp;lt;branch_name&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a pull request as we saw in the last post. &lt;/p&gt;

&lt;h3&gt;
  
  
  Here is where everything we've done in these 2 posts shines.
&lt;/h3&gt;

&lt;p&gt;First, you'll have to wait for the checks to complete. Specifically, the &lt;code&gt;build&lt;/code&gt; job that we configured to the master branch as &lt;code&gt;protection&lt;/code&gt;. If this doesn't complete successfully we aren't going to be able to merge.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qGeh5HvU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-merging.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qGeh5HvU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/github-merging.jpg" alt="github-merging"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Meanwhile you wait, on the CircleCI website the &lt;code&gt;build&lt;/code&gt; is running.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yTZkbHen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/feature-branch-circleci-job-success.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yTZkbHen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/feature-branch-circleci-job-success.jpg" alt="feature-branch-circleci-job-success"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;After we merge the pull request, the &lt;code&gt;deploy&lt;/code&gt; job runs on the master branch.&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0Of_f_D7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/master-branch-circleci-build-running.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0Of_f_D7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/master-branch-circleci-build-running.jpg" alt="master-branch-circleci-build-running"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;When completed, it triggers the &lt;code&gt;build hook&lt;/code&gt; from Netlify - the one we wrote in the environment variable on the CircleCI website. This triggers a build + deploy to our Netlify site - the one with the &lt;code&gt;.netlify.com&lt;/code&gt; extension.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E2sz3oaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-building-in-process.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E2sz3oaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-building-in-process.jpg" alt="netlify-building-in-process"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Finally, after Netlify's build succeeds our site is live&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ywH26QLM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-deploy-success.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ywH26QLM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/netlify-deploy-success.jpg" alt="netlify-deploy-success"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DONE&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/DffShiJ47fPqM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/DffShiJ47fPqM/giphy.gif" alt="yes!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Last words
&lt;/h2&gt;

&lt;p&gt;This ends our journey. You are now the proud owner of a project that tests and deploys automatically. Feel proud and you are allowed to overkill each one of your projects with these awesome features. Believe in your development game. You rock. &lt;/p&gt;

&lt;p&gt;Best wishes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/gdkVL0ljDHbNcXQOZD/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/gdkVL0ljDHbNcXQOZD/giphy.gif" alt="self-claps"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cicd</category>
      <category>github</category>
      <category>translate</category>
    </item>
    <item>
      <title>Upgrading Your Personal Project Game With  CircleCI + Netlify + Github - Part 1 [ENG]</title>
      <dc:creator>Sebastian Linares L.</dc:creator>
      <pubDate>Fri, 01 Nov 2019 19:49:07 +0000</pubDate>
      <link>https://dev.to/sebalinares/upgrading-your-personal-project-game-with-circleci-circleci-netlify-github-part-1-eng-5bp2</link>
      <guid>https://dev.to/sebalinares/upgrading-your-personal-project-game-with-circleci-circleci-netlify-github-part-1-eng-5bp2</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3GKyOKHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1559510981-10719ce4266a%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1350%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3GKyOKHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1559510981-10719ce4266a%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1350%26q%3D80" alt="pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;During the time I've been  learning to program - because I don't know if I can say I've studied &lt;em&gt;computer science&lt;/em&gt; as a whole-, I've done many little projects and other more ambitious - all just for learning purposes-, and as the time passes, I started building some criteria 🧠 about what's else, what spice can I add to those projects to enrich them in technologies. There is always the term "overkill" lurking around, but when it's just for learning purposes and you can set terms and goals ... just do it.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/CpgNjk2E54p7W/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/CpgNjk2E54p7W/giphy.gif" alt="do-it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For those who haven't hopped in the CI/CD train, here I bring you a comprehensive set of steps you can take to connect your beautiful, dusty and forgotten, &lt;code&gt;Todo App&lt;/code&gt;, that's been wandering for many months in your &lt;code&gt;/projects&lt;/code&gt; directory. &lt;/p&gt;

&lt;p&gt;I'll try to make this as short as possible, but it will be divided into 2 posts. This first post will be about &lt;em&gt;continuous delivery&lt;/em&gt; and the second, I'm still not sure if it is &lt;strong&gt;continuous delivery&lt;/strong&gt; or &lt;strong&gt;continuous deployment&lt;/strong&gt;, BUT the technical terminology is the homework, I'm just here to show you the door, you're the one who crosses it and determines what is made of. Off we go ‼️.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/LmrlNycquCmOPFM6WR/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LmrlNycquCmOPFM6WR/giphy.gif" alt="go"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  End result 🔚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic app 👶🏽&lt;/li&gt;
&lt;li&gt;Github repository with two branches: &lt;code&gt;master&lt;/code&gt; and &lt;code&gt;circleci&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A CircleCI account&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;.yml&lt;/code&gt; file that serves as configuration for CircleCI. It will trigger your test suite every you push content to the &lt;code&gt;origin/circleci&lt;/code&gt; you were working on.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Continuous Integration (CI) 🤝
&lt;/h2&gt;

&lt;p&gt;As Microsoft describes it, &lt;em&gt;continuous integration&lt;/em&gt; is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;... the process of automating the build and testing of code every time a team member commits changes to version control. - &lt;a href="https://docs.microsoft.com/en-us/azure/devops/learn/what-is-continuous-integration"&gt;microsoft docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simple words, for me, CI means that every time we make &lt;code&gt;git push&lt;/code&gt;, it triggers a set of tasks, previously configured, that culminate with our app to go through multiple tests and/or builds. All this to validate the integrity of the code that you &lt;code&gt;push&lt;/code&gt; to your remote repositories, either to Github, Gitlab, Bitbucket or other remote version control system of your preference, so at this point we are able to say: &lt;em&gt;Ok, the build that originated with the changes on this last commit went through the testing suite without breaking, maybe this is ready for **production&lt;/em&gt;*&lt;/p&gt;
&lt;h3&gt;
  
  
  First Step 1️⃣
&lt;/h3&gt;

&lt;p&gt;Actually, I'm not starting from the first stem, but you do it on your computers. I'm creating a new app with &lt;code&gt;yarn create react-app&lt;/code&gt; and connecting it to a Github repository. From this point, I'll assume you've all done that.&lt;/p&gt;
&lt;h3&gt;
  
  
  Second step: Protect master branch in Github 2️⃣
&lt;/h3&gt;

&lt;p&gt;On the main page of our Github repository, let's go &lt;code&gt;settings&lt;/code&gt; and then &lt;code&gt;branches&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/gLd9ihsbKl2aZbISB8/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/gLd9ihsbKl2aZbISB8/giphy.gif" alt="setting-branch-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we click in &lt;code&gt;Add Rule&lt;/code&gt;, in &lt;code&gt;Branch name pattern&lt;/code&gt; we write &lt;em&gt;master&lt;/em&gt;. Then click in &lt;code&gt;Require status checks to pass before merging&lt;/code&gt;, &lt;code&gt;Require branch to be up to date before merging&lt;/code&gt;, finally let's click in &lt;code&gt;Include administrators&lt;/code&gt;. The last click ensures that &lt;strong&gt;everyone&lt;/strong&gt; has to respect the &lt;em&gt;checks&lt;/em&gt; you set to the branch you are protecting, which includes administrators. If we do not check it, we will still be able to merge our &lt;em&gt;feature branch&lt;/em&gt; with &lt;em&gt;master&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;As you can see, the options panel displays is a message that says &lt;code&gt;Sorry, we couldn't find any status checks ...&lt;/code&gt;. This message appears because our repository doesn't know about the possible &lt;em&gt;checks&lt;/em&gt; that we will create in the &lt;strong&gt;CircleCI&lt;/strong&gt; config file. &lt;br&gt;
&lt;a href="https://i.giphy.com/media/eJdJ61YE0k3sim2uuB/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/eJdJ61YE0k3sim2uuB/giphy.gif" alt="setting-branch-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let add this file immediately 🏃🏽‍♂️.&lt;/p&gt;
&lt;h3&gt;
  
  
  Third step: CircleCI 3️⃣
&lt;/h3&gt;

&lt;p&gt;To be able to have continuous integration in our project we'll use the services that CircleCI's free tier delivers me - which by the way is more than enough for our small projects. We can find the website in &lt;a href="https://circleci.com"&gt;this link&lt;/a&gt;. We register with Github and we'll have access yo all our repositories in the &lt;strong&gt;dashboard&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The file we are creating has a &lt;code&gt;.yml&lt;/code&gt; extension -YAML Ain't Markup Language-, which gives us the possibility of setting the steps, for a good configuration file, in a human legible way 👇🏽.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;ADD PROJECTS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;To the right of your project, it will say &lt;code&gt;Set Up Project&lt;/code&gt;. Click here&lt;/li&gt;
&lt;li&gt;Choose &lt;code&gt;Node&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scroll down the page and we will see a configuration file template. Copy it&lt;/li&gt;
&lt;li&gt;In our local repository, create and checkout to a new branch with the name of the feature you are adding to it, in this case, we will create one named &lt;code&gt;circleci&lt;/code&gt; --&amp;gt; &lt;code&gt;git checkout -b circleci&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a directory named &lt;code&gt;.circleci&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inside that directory create a file named &lt;code&gt;config.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Paste the configuration file template copied before👇🏽
&lt;img src="https://i.giphy.com/media/Z8k5OZgo8WSjiBIuly/giphy.gif" alt="config-file-template"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our configuration file should look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&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;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# specify the version you desire here&lt;/span&gt;
      &lt;span class="pi"&gt;-&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;circleci/node:7.10&lt;/span&gt;

      &lt;span class="c1"&gt;# Specify service dependencies here if necessary&lt;/span&gt;
      &lt;span class="c1"&gt;# CircleCI maintains a library of pre-built images&lt;/span&gt;
      &lt;span class="c1"&gt;# documented at https://circleci.com/docs/2.0/circleci-images/&lt;/span&gt;
      &lt;span class="c1"&gt;# - image: circleci/mongo:3.4.4&lt;/span&gt;

    &lt;span class="na"&gt;working_directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/repo&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="s"&gt;checkout&lt;/span&gt;

      &lt;span class="c1"&gt;# Download and cache dependencies&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;restore_cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;
            &lt;span class="c1"&gt;# fallback to using the latest cache if no exact match is found&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;save_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;node_modules&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;

      &lt;span class="c1"&gt;# run tests!&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Forth Step: Do The First Push 4️⃣
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Let's stage our changes to the &lt;em&gt;circleci&lt;/em&gt; directory with &lt;code&gt;git add .circleci/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Commit the changes&lt;/li&gt;
&lt;li&gt;We Push them to our remote with &lt;code&gt;git push -u origin circleci&lt;/code&gt;. This will generate a new remote branch with the same name as the local one - origin/circleci&lt;/li&gt;
&lt;li&gt;Go to our Github repository&lt;/li&gt;
&lt;li&gt;We will find a green button that says &lt;code&gt;Create pull request&lt;/code&gt;. If it doesn't appear, we create the pull request ourself👇🏽
&lt;img src="https://i.giphy.com/media/H1A305gMub8pBfeeNm/giphy.gif" alt="crear-pull-request"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notice that the &lt;code&gt;Merge pull request button&lt;/code&gt; is disabled. This is because we &lt;strong&gt;protected&lt;/strong&gt; master with the &lt;code&gt;circleci: build&lt;/code&gt; check. Thus, meanwhile the check is not approved, we won't be able to merge 😡.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/giQyAaSEkPsM25htum/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/giQyAaSEkPsM25htum/giphy.gif" alt="come-on"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let's debug! The build failed and we need to check &lt;strong&gt;why&lt;/strong&gt; 🤷🏽‍♂️. &lt;br&gt;
&lt;a href="https://i.giphy.com/media/JQG1Q2awvX3vUxsYdz/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/JQG1Q2awvX3vUxsYdz/giphy.gif" alt="build-fails"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the same Github page, next to the build that fails, the one with the ❌, we see a hyperlink &lt;code&gt;Details&lt;/code&gt;, click it. That takes us to our CircleCI account, specifically to the 'Job' that failed. There it clearly says that we need a Node version that is &lt;code&gt;&amp;gt;=8.10&lt;/code&gt;. There it is! Let's fix it 👷🏽‍♂️.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0LVfEqaB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/circleci-fails-node-version.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0LVfEqaB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/circleci-fails-node-version.jpg" alt="circleci-fails-node-version"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to the &lt;code&gt;config.yml&lt;/code&gt; file in our local repository and on line 5 change the version of your node image.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# image: circleci/node:7.10 &amp;lt;-- Change this&lt;/span&gt;
&lt;span class="pi"&gt;-&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;circleci/node:lts&lt;/span&gt; &lt;span class="c1"&gt;# For this.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;We save the file, stage our changes and push them to Github with &lt;code&gt;git add. &amp;amp;&amp;amp; git commit -m 'fix(ci): change to node:lts' &amp;amp;&amp;amp; git push&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Head to our Github repository and in the &lt;em&gt;Pull request&lt;/em&gt; tab we can see there is a "(1)", that's our old pull request, it's still alive 👻. For it to disappear we have to explicitly close it or merge it, if not, it will be there, receiving every other commit you push to the branch we are trying to merge with, in this case &lt;code&gt;origin/circleci&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Now the build check passes 👏🏽
&lt;img src="https://i.giphy.com/media/MCivExf510LGhqLOzH/giphy.gif" alt="build-success"&gt;
&lt;/li&gt;
&lt;li&gt;Finally, click &lt;code&gt;Merge&lt;/code&gt; and then we can delete the branch from your Github - then we can do the same in our local repository. 
&lt;img src="https://i.giphy.com/media/S667pS1XsodQjzpD05/giphy.gif" alt="merge-pull-request"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And &lt;strong&gt;&lt;em&gt;voilà&lt;/em&gt;&lt;/strong&gt; we just made our first step in the looong way of continuous integration 🏆. In the next post we'll use Netlify as a hosting for this app and I'll implement &lt;strong&gt;Continuous Delivery&lt;/strong&gt; with a new configuration file and some Netlify spices, so the deploy process is automatized, plus a way to make the &lt;code&gt;build&lt;/code&gt; process faster using the &lt;code&gt;cache&lt;/code&gt; commands that CircleCI has available for us.&lt;/p&gt;

&lt;p&gt;👾 &lt;a href="https://twitter.com/SLinaresL"&gt;Here is my Twitter account, sometimes I post about web development&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope it's useful, Chao!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7uL_fke---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://statics.memondo.com/p/99/gifs/2012/05/GIF_113206_3bb8f57d5ca2453f8551a243a06a3faf_exito_origen_del_meme.mp4" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7uL_fke---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://statics.memondo.com/p/99/gifs/2012/05/GIF_113206_3bb8f57d5ca2453f8551a243a06a3faf_exito_origen_del_meme.mp4" alt="exito"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Github Flow
&lt;/h2&gt;

&lt;p&gt;The way I manage my version control system is known as &lt;em&gt;Github Flow&lt;/em&gt;, and it goes like this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everything in &lt;code&gt;master&lt;/code&gt; is deployable&lt;/li&gt;
&lt;li&gt;To work on something new, create a descriptively named branch off of &lt;code&gt;master&lt;/code&gt; (ie: &lt;code&gt;new-circleci&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Commit to that branch locally and regularly push your work to the same-named branch on the server&lt;/li&gt;
&lt;li&gt;When you need feedback or help, or you think the branch is ready for merging, open a &lt;strong&gt;pull request&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;After someone else has reviewed and signed off on the feature, you can merge it into master&lt;/li&gt;
&lt;li&gt;Once it is merged and pushed to &lt;code&gt;master&lt;/code&gt;, you can and should deploy immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Keywords
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Continuous Development&lt;/li&gt;
&lt;li&gt;Continuous Delivery&lt;/li&gt;
&lt;li&gt;Github Flow&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>circleci</category>
      <category>github</category>
      <category>netlify</category>
      <category>translated</category>
    </item>
    <item>
      <title>Profesionaliza tus proyectos personales con CircleCi + Netlify + Github Parte 1 [ESP]</title>
      <dc:creator>Sebastian Linares L.</dc:creator>
      <pubDate>Fri, 01 Nov 2019 19:49:01 +0000</pubDate>
      <link>https://dev.to/sebalinares/profesionaliza-tus-proyectos-personales-con-circleci-netlify-github-parte-1-esp-3l5j</link>
      <guid>https://dev.to/sebalinares/profesionaliza-tus-proyectos-personales-con-circleci-netlify-github-parte-1-esp-3l5j</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3GKyOKHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1559510981-10719ce4266a%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1350%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3GKyOKHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1559510981-10719ce4266a%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1350%26q%3D80" alt="pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Durante mi tiempo estudiando a programar - porque no sé si decir que he estudiado la "informática" como tal -, he hecho varios proyectos pequeños y otros un poco más ambiciosos - todos proyectos personales -, y a medida que ha pasado el tiempo, me he ido formando algo de criterio 🧠 acerca de qué cosa extra, que picante le puedo agregar a esos proyectos para enriquecerlos en tecnologías y a su vez enriquecer mis conocimientos. Siempre está el fantasma del &lt;em&gt;overkill&lt;/em&gt; deambulando, pero cuando es por aprender y uno sabe sus tiempos y objetivos, solo hazlo. &lt;br&gt;
&lt;a href="https://i.giphy.com/media/CpgNjk2E54p7W/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/CpgNjk2E54p7W/giphy.gif" alt="do-it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para aquellos que aún no se suben al tren del CI/CD, aquí les va una lista comprensiva de pasos a seguir para conectar su preciada, empolvada y olvidada &lt;code&gt;Todo App&lt;/code&gt; que ha estado en el olvido en su carpeta &lt;code&gt;/proyectos&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Trataré de hacer esto lo más corto posible y lo dividiré en 2 posts. El primero será acerca del &lt;strong&gt;desarrollo continuo&lt;/strong&gt; y el segundo, todavía no estoy seguro si es &lt;strong&gt;entrega continua&lt;/strong&gt; o &lt;strong&gt;despliegue continuo&lt;/strong&gt;, &lt;strong&gt;pero&lt;/strong&gt; los tecnisismos es tarea de cada uno, yo solo estoy aquí para mostrarles la puerta y ustedes tienen que ver de qué está hecha, cruzarla, etc. Vamos‼️&lt;br&gt;
&lt;a href="https://i.giphy.com/media/LmrlNycquCmOPFM6WR/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LmrlNycquCmOPFM6WR/giphy.gif" alt="go"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Resultado Final Del Post 🔚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Una app básica 👶🏽&lt;/li&gt;
&lt;li&gt;Un repositorio en Github que funcionará con una rama &lt;code&gt;master&lt;/code&gt; y una &lt;code&gt;circleci&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Una cuenta en CircleCI&lt;/li&gt;
&lt;li&gt;Un archivo &lt;code&gt;.yml&lt;/code&gt; de configuración CircleCI que hará un test básico cada vez que hagamos &lt;code&gt;push&lt;/code&gt; a &lt;code&gt;origin/circleci&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Integración Continua (CI) 🤝
&lt;/h2&gt;

&lt;p&gt;Integración continua o Continous Integration - de ahí el CI -, según lo describe Microsoft es &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;... el proceso de automatizar el build y el testing del código, cada vez que un miembro del equipo hace &lt;code&gt;commit&lt;/code&gt; a un sistema de control de versionamiento (&lt;code&gt;git&lt;/code&gt;). - &lt;a href="https://docs.microsoft.com/en-us/azure/devops/learn/what-is-continuous-integration"&gt;microsoft docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En palabras sencillas - para mi -, es que cada vez que hacemos &lt;code&gt;git push origin &amp;lt;rama_de_elección&amp;gt;&lt;/code&gt; se desencadenen una serie de procesos que culminan con que nuestra app pase por un suite de testing. Todo esto para validar la integridad del código que se "sube" a un repositorio, ya sea Github, Gitlab, Bitbucket u otro, y poder decir: "Ok, el build que se originó de mi &lt;code&gt;commit&lt;/code&gt; reciente paso por el testing sin romperse, quizás está listo para &lt;code&gt;producción&lt;/code&gt;. &lt;/p&gt;
&lt;h3&gt;
  
  
  Primer paso 1️⃣
&lt;/h3&gt;

&lt;p&gt;En realidad no voy a partir del primer paso, pero ustedes lo hacen con sus proyectos personales. Yo voy a crear una app con &lt;code&gt;yarn create react-app&lt;/code&gt; y la voy a conectar con un repositorio en github. Así que supondré que todos ya hicieron eso para continuar.&lt;/p&gt;
&lt;h3&gt;
  
  
  Segundo paso: Proteger la rama de github 2️⃣
&lt;/h3&gt;

&lt;p&gt;Vamos a los &lt;code&gt;settings&lt;/code&gt; de nuestro repositorio y ahí entramos en &lt;code&gt;branches&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/gLd9ihsbKl2aZbISB8/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/gLd9ihsbKl2aZbISB8/giphy.gif" alt="setting-branch-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luego hacemos click en &lt;code&gt;Add rule&lt;/code&gt;, en donde dice &lt;code&gt;Branch name pattern&lt;/code&gt; escribimos &lt;code&gt;master&lt;/code&gt;. Luego elejimos &lt;code&gt;Require status checks to pass before merging&lt;/code&gt;, después hacemos click en &lt;code&gt;Require branch to be up to date before merging&lt;/code&gt;, y finalmente click en &lt;code&gt;Include administrator&lt;/code&gt; porque o si no de todas maneras podrán hacer merge si son administradores, lo cual rompe completamente el sentido de hacer estos &lt;code&gt;checks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Se darán cuenta que les dice un mensaje &lt;code&gt;Sorry, we coudn't find any status checks ...&lt;/code&gt;. Este mensaje es porque todavía su repositorio no sabe que tiene disponible posibles "checks" que son los que crearemos en la configuración de &lt;code&gt;CircleCI&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/eJdJ61YE0k3sim2uuB/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/eJdJ61YE0k3sim2uuB/giphy.gif" alt="setting-branch-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lo arreglamos inmediatamente 🏃🏽‍♂️.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tercer paso: CircleCI 3️⃣
&lt;/h3&gt;

&lt;p&gt;Para poder tener integración continua en nuestro proyecto utilizaremos los servicios que nos presta el free tier de CircleCi - que es más que suficiente para nuestros pequeños proyectos personales, podemos encontrar la página en &lt;a href="https://circleci.com"&gt;este link&lt;/a&gt;, nos registramos con github y tendremos acceso automático a nuestros repositorios en el &lt;code&gt;dashboard&lt;/code&gt; de CircleCI.&lt;/p&gt;

&lt;p&gt;El archivo que crearemos tiene la extensión &lt;code&gt;.yml&lt;/code&gt; -YAML Ain't Markup Language-, el cual nos permite, de una manera muy legible para humanos, escribir un archivo de configuración para nuestra &lt;code&gt;build&lt;/code&gt; de CircleCI 👇🏽. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vamos a &lt;code&gt;ADD PROJECTS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A la derecha del nombre de nuestro proyecto dirá &lt;code&gt;Set Up Project&lt;/code&gt;. Hacemos click ahí, &lt;/li&gt;
&lt;li&gt;Elejimos &lt;code&gt;Node&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Más abajo nos aparecerá un template para el archivo de configuración básica. &lt;/li&gt;
&lt;li&gt;Copiamos esa configuración.&lt;/li&gt;
&lt;li&gt;Creamos una carpeta, además una branch que se llame &lt;em&gt;circleci&lt;/em&gt; y hacemos checkout a esa branch con &lt;code&gt;git checkout -b circleci&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Creamos un directorio con el nombre &lt;code&gt;.circleci/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adentro de esa carpeta creamos un archivo &lt;code&gt;config.yml&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Pegamos lo que copiaron antes 👇🏽.
&lt;img src="https://i.giphy.com/media/Z8k5OZgo8WSjiBIuly/giphy.gif" alt="config-file-template"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nuestro archivo de configuración debería verse así 👇🏽.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&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;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# specify the version you desire here&lt;/span&gt;
      &lt;span class="pi"&gt;-&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;circleci/node:7.10&lt;/span&gt;

      &lt;span class="c1"&gt;# Specify service dependencies here if necessary&lt;/span&gt;
      &lt;span class="c1"&gt;# CircleCI maintains a library of pre-built images&lt;/span&gt;
      &lt;span class="c1"&gt;# documented at https://circleci.com/docs/2.0/circleci-images/&lt;/span&gt;
      &lt;span class="c1"&gt;# - image: circleci/mongo:3.4.4&lt;/span&gt;

    &lt;span class="na"&gt;working_directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/repo&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="s"&gt;checkout&lt;/span&gt;

      &lt;span class="c1"&gt;# Download and cache dependencies&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;restore_cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;
            &lt;span class="c1"&gt;# fallback to using the latest cache if no exact match is found&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;save_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;node_modules&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1-dependencies-{{ checksum "package.json" }}&lt;/span&gt;

      &lt;span class="c1"&gt;# run tests!&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Cuarto paso: Hacer el primer push 4️⃣
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Agregamos los cambios al directorio &lt;em&gt;circleci&lt;/em&gt; con &lt;code&gt;git add .circleci/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Hacemos commit de esos cambios.&lt;/li&gt;
&lt;li&gt;Hacemos &lt;code&gt;push&lt;/code&gt; con &lt;code&gt;git push -u origin circleci&lt;/code&gt;. Esto creará una rama remota con el mismo nombre que la rama local -origin/circleci.&lt;/li&gt;
&lt;li&gt;Vamos a nuestro repositorio en Github.com&lt;/li&gt;
&lt;li&gt;Vamos a encontrar una nueva pestaña que dice &lt;code&gt;Create pull request&lt;/code&gt;. Si no nos aparece, creamos nosotros mismos el &lt;code&gt;pull request&lt;/code&gt; 👇🏽.
&lt;img src="https://i.giphy.com/media/H1A305gMub8pBfeeNm/giphy.gif" alt="crear-pull-request"&gt;
&lt;/li&gt;
&lt;li&gt;Si nos fijamos, el botón &lt;code&gt;Merge pull request&lt;/code&gt; esta deshabilitado. Esto es porque ya protegimos &lt;code&gt;master&lt;/code&gt; con &lt;code&gt;circleci:build&lt;/code&gt;. Por lo tanto, mientras no pase eso, no podremos realizar el &lt;code&gt;merge&lt;/code&gt; 😡.
&lt;img src="https://i.giphy.com/media/giQyAaSEkPsM25htum/giphy.gif" alt="come-on"&gt;
&lt;/li&gt;
&lt;li&gt;¡Hagamos debug! La build falló y hay que revisar por qué 🤷🏽‍♂️. 
&lt;img src="https://i.giphy.com/media/JQG1Q2awvX3vUxsYdz/giphy.gif" alt="build-fails"&gt;
&lt;/li&gt;
&lt;li&gt;En la misma página de Github, a la derecha de la build que fallo, la que tiene la ❌, veremos un hyperlink &lt;code&gt;Details&lt;/code&gt;, hagamos click. Esto nos lleva a nuestra cuenta de CircleCI, específicamente al &lt;code&gt;Job&lt;/code&gt; que falló. Ahí dice claramento q espera que nuestra versión de node sea &lt;code&gt;&amp;gt;=8.10&lt;/code&gt;. Aquí está el problema. Arreglemos 👷🏽‍♂️
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0LVfEqaB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sebaLinares/screenshots/master/blog-posts/ci-cd-blog/circleci-fails-node-version.jpg" alt="circleci-fails-node-version"&gt;
&lt;/li&gt;
&lt;li&gt;Vamos al archivo &lt;code&gt;config.yml&lt;/code&gt; en nuestro repositorio local y cambiamos la línea 5 de código.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# image: circleci/node:7.10 &amp;lt;-- Change this&lt;/span&gt;
&lt;span class="pi"&gt;-&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;circleci/node:lts&lt;/span&gt; &lt;span class="c1"&gt;# For this.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Guardamos el archivo, lo agregamos, hacemos &lt;code&gt;commit&lt;/code&gt; y &lt;code&gt;push&lt;/code&gt;  con &lt;code&gt;git add. &amp;amp;&amp;amp; git commit -m 'fix(ci): change to node:lts' &amp;amp;&amp;amp; git push&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Vayamos a nuestro repositorio Github y en la pestaña &lt;em&gt;Pull request&lt;/em&gt;, debería ver que dice "(1)", ese es nuestro antiguo pull request, el que falló, aún está "vivo" 👻. Para que desaparezca tenemos que explicitamente hacer merge o cerrarlo, si no, estará ahí, recibiendo otros commits de algún push que hagamos en nuestro repositorio local&lt;/li&gt;
&lt;li&gt;Ahora si la la &lt;code&gt;build&lt;/code&gt; de CircleCI fue exitosa👇🏽
&lt;img src="https://i.giphy.com/media/MCivExf510LGhqLOzH/giphy.gif" alt="build-success"&gt;
&lt;/li&gt;
&lt;li&gt;Finalmente hacemos click en &lt;code&gt;Merge&lt;/code&gt; y luego podemos borrar el branch - podemos hacer lo mismo en nuestro repositorio local👇🏽.
&lt;img src="https://i.giphy.com/media/S667pS1XsodQjzpD05/giphy.gif" alt="merge-pull-request"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Y &lt;strong&gt;&lt;em&gt;voilá!&lt;/em&gt;&lt;/strong&gt; dimos el primer paso en el laaargo camino de la integración continua 🥇. En el siguiente post utilizaremos Netlify como hosting para nuestra aplicación e implementaremos la &lt;strong&gt;Entrega Continua&lt;/strong&gt; para que nuestro deploy se automatice, completando esta serie de posts 📝. Además les mostraré como hacer que nuestros &lt;code&gt;jobs&lt;/code&gt; de circleci se hagan más rápido utilizando un &lt;code&gt;cache&lt;/code&gt; de las dependencias, cambiando la configuración de su archivo &lt;code&gt;config.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;👾 &lt;a href="https://twitter.com/SLinaresL"&gt;Aquí les dejo mi Twitter, a veces posteo sobre desarrollo web&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¡Espero les sirva, saludos!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7uL_fke---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://statics.memondo.com/p/99/gifs/2012/05/GIF_113206_3bb8f57d5ca2453f8551a243a06a3faf_exito_origen_del_meme.mp4" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7uL_fke---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://statics.memondo.com/p/99/gifs/2012/05/GIF_113206_3bb8f57d5ca2453f8551a243a06a3faf_exito_origen_del_meme.mp4" alt="exito"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Github Flow
&lt;/h2&gt;

&lt;p&gt;La forma en la que manejo mi control de versiones es más conocida como &lt;em&gt;Github Flow&lt;/em&gt;, que va así:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Todo en &lt;code&gt;master&lt;/code&gt; es deployable&lt;/li&gt;
&lt;li&gt;Para trabajar en algo nuevo crea una &lt;code&gt;branch&lt;/code&gt;, desde master, con un nombre descriptivo - por ejemplo, &lt;em&gt;nuevo-menu&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;Agrega todos los &lt;code&gt;commit&lt;/code&gt; que quieras a tu nueva &lt;code&gt;branch&lt;/code&gt; &lt;em&gt;nuevo-menu&lt;/em&gt; y ve haciendo &lt;code&gt;push&lt;/code&gt; esos cambios a una &lt;code&gt;branch&lt;/code&gt; remota con el mismo nombre&lt;/li&gt;
&lt;li&gt;Cuando creas que está lista tu nueva &lt;code&gt;feature&lt;/code&gt; abre un &lt;a href="https://help.github.com/es/github/collaborating-with-issues-and-pull-requests/about-pull-requests"&gt;pull request&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si trabajas en equipo, luego de que alguien revise tu &lt;code&gt;pull request&lt;/code&gt;, puedes hacerle &lt;code&gt;merge&lt;/code&gt; hacia master&lt;/li&gt;
&lt;li&gt;Una vez que se completa el &lt;code&gt;merge&lt;/code&gt; debería haber un &lt;code&gt;deploy&lt;/code&gt; inmediatamente&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Palabras clave
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Desarrollo continuo&lt;/li&gt;
&lt;li&gt;Entrega Continua&lt;/li&gt;
&lt;li&gt;Github Flow&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>circleci</category>
      <category>github</category>
      <category>netlify</category>
      <category>translated</category>
    </item>
  </channel>
</rss>
