<?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: Fabio Gallotti</title>
    <description>The latest articles on DEV Community by Fabio Gallotti (@fabiogallotti).</description>
    <link>https://dev.to/fabiogallotti</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%2F381888%2Fa16ff749-73e2-4f7f-9d28-05e10be46f3a.jpeg</url>
      <title>DEV Community: Fabio Gallotti</title>
      <link>https://dev.to/fabiogallotti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fabiogallotti"/>
    <language>en</language>
    <item>
      <title>Setting up a CI pipeline with CircleCI</title>
      <dc:creator>Fabio Gallotti</dc:creator>
      <pubDate>Fri, 08 May 2020 09:04:03 +0000</pubDate>
      <link>https://dev.to/fabiogallotti/setting-up-a-ci-pipeline-with-circleci-42i</link>
      <guid>https://dev.to/fabiogallotti/setting-up-a-ci-pipeline-with-circleci-42i</guid>
      <description>&lt;p&gt;Have you ever wondered how to properly setup the Continuous Integration for you new &lt;a href="https://github.com/"&gt;Github&lt;/a&gt; repository? Let’s dive deep on it together!&lt;/p&gt;




&lt;h3&gt;
  
  
  Overview of the tools used
&lt;/h3&gt;

&lt;p&gt;In this tutorial I will help you configure &lt;a href="https://www.circleci.com"&gt;CircleCI&lt;/a&gt; to setup your builds, running on a customized &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; image. I will focus on a Python codebase, using &lt;a href="https://docs.pytest.org/en/latest/"&gt;pytest&lt;/a&gt; for test automation and &lt;a href="https://pypi.org/project/pytest-cov/"&gt;pytest-cov&lt;/a&gt; for coverage reports generation.&lt;/p&gt;

&lt;p&gt;In addition, I will explain you how to setup &lt;a href="https://codeclimate.com/"&gt;Code Climate&lt;/a&gt;, a useful tool to statically analyze your code, and &lt;a href="https://codecov.io/"&gt;Codecov&lt;/a&gt;, that will help you better visualize the coverage of your code.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Practical how-to&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;We will take as example the following repository: &lt;a href="https://github.com/fabiogallotti/tutorial_ci"&gt;tutorial_ci&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up CircleCI
&lt;/h3&gt;

&lt;p&gt;The first thing we need to do is creating, at the root of our repository, a folder &lt;em&gt;.circleci&lt;/em&gt;, where we will create the file &lt;em&gt;config.yml .&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a test, let’s start with the default “Hello World” workflow:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For the sake of this example, we can directly commit our change on the master branch of your repository.&lt;/p&gt;

&lt;p&gt;Then we need to sign up with our Github account to &lt;a href="https://circleci.com/signup/"&gt;CircleCI&lt;/a&gt;…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RLYJQoqS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4444/1%2A-0T-Ue32cedU27uhB2fz-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RLYJQoqS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4444/1%2A-0T-Ue32cedU27uhB2fz-g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…and select the repository we want to build, clicking on &lt;em&gt;Set Up Project&lt;/em&gt; and in the following window, on &lt;em&gt;Add Manually *and on&lt;/em&gt; Start Building*&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hOrNMzWi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4068/1%2AuXb5TInZGm5nsdVaDdCZAw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hOrNMzWi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4068/1%2AuXb5TInZGm5nsdVaDdCZAw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--99SeUchA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4084/1%2AGNpwAWxIU0BXop4W_Zegbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--99SeUchA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4084/1%2AGNpwAWxIU0BXop4W_Zegbw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ccnAHrKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3212/1%2A5ScdFH1gaxH-jGnBlDqkOg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ccnAHrKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3212/1%2A5ScdFH1gaxH-jGnBlDqkOg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here it is, our first working build!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KdMgowDm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4652/1%2AjGt-SSihqTUK_Pruba_qDA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KdMgowDm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4652/1%2AjGt-SSihqTUK_Pruba_qDA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Custom Docker Image
&lt;/h3&gt;

&lt;p&gt;As of now, our build is not doing much, so let’s start doing some customization. All what we need to change is the &lt;em&gt;.circleci/config.yml&lt;/em&gt; file. (&lt;strong&gt;note:&lt;/strong&gt; y*ou can always validate your .yml file using &lt;a href="http://www.yamllint.com/"&gt;yamllint&lt;/a&gt;.*)&lt;/p&gt;

&lt;p&gt;The first customization I want to explain it’s how to generate and use a custom Docker image in your builds. To do so, you need to have an account on &lt;a href="https://hub.docker.com/"&gt;Docker Hub&lt;/a&gt;, where you will push the image to use.&lt;/p&gt;

&lt;p&gt;If you don’t have an existing account, Sign Up and chose the Community plan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LIDnnOAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2432/1%2Ak7zxeYkpgmIzmz54RvVadA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LIDnnOAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2432/1%2Ak7zxeYkpgmIzmz54RvVadA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1QOcEoR2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3708/1%2Ai5f1RBrQUiZjTTkZuFTM1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1QOcEoR2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3708/1%2Ai5f1RBrQUiZjTTkZuFTM1g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once validated your email, you can start creating a repository, where you can push the image we are going to create. We will call it tutorial_ci and keep it public.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--siYwe874--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2836/1%2AyW7RQsj5M8S8O--oTQQjhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--siYwe874--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2836/1%2AyW7RQsj5M8S8O--oTQQjhw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Let’s create the image!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As I told you, we will focus on a Python codebase, so for this example we will create, in a folder &lt;em&gt;docker&lt;/em&gt; at the root of the repository, the following &lt;em&gt;Dockerfile&lt;/em&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;and &lt;em&gt;requirements.txt&lt;/em&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the folder docker, we need to build our image, with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t &amp;lt;your_user_name&amp;gt;/tutorial_ci .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and then push it to Docker Hub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push &amp;lt;your_user_name&amp;gt;/tutorial_ci
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Here it is, ready to be used for our builds:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9-O3xS0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5136/1%2AOoIKW0jH0VFNXB16h2pzsA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9-O3xS0K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5136/1%2AOoIKW0jH0VFNXB16h2pzsA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the config.yml, we will remove the usage of an external orb, and we will create our customized jobs using our newly created docker image.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;To give you a bit of details, we are defining a new job called “hello”, that will run on the image we just created, and will print out “Hello World”. The workflow “hello” will run this job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WfEpTq-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4656/1%2A4ekldsUVLzQ-nBcaC0E_Ag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WfEpTq-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4656/1%2A4ekldsUVLzQ-nBcaC0E_Ag.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Setting up Code Climate
&lt;/h3&gt;

&lt;p&gt;What if we want some static analysis of our code?&lt;/p&gt;

&lt;p&gt;We will start &lt;a href="https://codeclimate.com/login/github/join"&gt;linking our github account to Code Climate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vfu1YmlR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2408/1%2A-K7XJt98UYQrnAr8LMlc4Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vfu1YmlR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2408/1%2A-K7XJt98UYQrnAr8LMlc4Q.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and adding our repository&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m_GTFoq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3476/1%2AYQhaKqGeocYyO6_8vH4pMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m_GTFoq---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3476/1%2AYQhaKqGeocYyO6_8vH4pMg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will be prompt a warning related to having only a Dockerfile at this stage, you can proceed, and you will have your first build completed!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pV1R_ro2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2136/1%2AV1y0TBOVZk9DEGjyHQ5pQQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pV1R_ro2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2136/1%2AV1y0TBOVZk9DEGjyHQ5pQQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Repo Setting, Github tab, enable all the features clicking on the first &lt;em&gt;Set Up&lt;/em&gt;; this way you will allow Code Climate to provide useful comments in your Pull Request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PxDHd-5L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3500/1%2AAit7fTwaFOhTvhukR8W11w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PxDHd-5L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3500/1%2AAit7fTwaFOhTvhukR8W11w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give permission to Code Climate:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dms-hqgW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2344/1%2AAfTq22xJ030-OyLaTGuYzA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dms-hqgW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2344/1%2AAfTq22xJ030-OyLaTGuYzA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code Climate offers also the possibility to have some visualization of the coverage of your code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NdUWGgBJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4544/1%2AL2eynZkNFwQjiRJDq7054w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NdUWGgBJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4544/1%2AL2eynZkNFwQjiRJDq7054w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s configure it in our &lt;em&gt;config.yml&lt;/em&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We first setup the test-reported, before the run of the test. Then we use pytest to run the tests, and we generate a coverage.xml file. Finally we upload the results to Code Climate.&lt;/p&gt;

&lt;p&gt;There is one step missing though! We need to configure an Environment Variable in our CircleCI, in order to have everything working. Let’s do it, from the Project Settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LtppouGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5608/1%2Ad26RVBhcT-StGnid9PNR0A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LtppouGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5608/1%2Ad26RVBhcT-StGnid9PNR0A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The variable we need to add is called CC_TEST_REPORTER_ID, and the value for it is available in the Repo Setting of our Code Climate account: (&lt;em&gt;I regenerated mine after taking the screenshot&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--APFW0T1L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4364/1%2Ajv_z9Oyo0cX9zg4gWiDVtA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--APFW0T1L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4364/1%2Ajv_z9Oyo0cX9zg4gWiDVtA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we add it, this is what we have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Di0hgKW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4072/1%2AfPnTzXH0lvj6yPIjYjo13w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Di0hgKW9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4072/1%2AfPnTzXH0lvj6yPIjYjo13w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we then push our changes to the central repository, we will have a failed build, because we don’t have any code yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cgd2aZGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4644/1%2AEEHeFXXQFRfNmPy9QUfNZw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cgd2aZGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4644/1%2AEEHeFXXQFRfNmPy9QUfNZw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s create a basic function and a test to in order to have some results:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the build it’s green, and we have our statistics on Code Climate!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I2hGf2Z7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4640/1%2AZk5fLuhwiIi2qQmnZW9Dlg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I2hGf2Z7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4640/1%2AZk5fLuhwiIi2qQmnZW9Dlg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u2krMjDQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4520/1%2AAiZRhztd5sQlQsWEtc0eyQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u2krMjDQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4520/1%2AAiZRhztd5sQlQsWEtc0eyQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up CodeCov
&lt;/h3&gt;

&lt;p&gt;And what if we want some more coverage visualization for our code? Maybe even detailed at Pull Request time? CodeCov will help us on this.&lt;/p&gt;

&lt;p&gt;Again, we will &lt;a href="https://codecov.io/gh"&gt;link Github and CodeCov&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OLqX5Cx6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5424/1%2ACRJK8E1Vxa4ZaApgLbZI0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OLqX5Cx6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5424/1%2ACRJK8E1Vxa4ZaApgLbZI0w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will need again to create an Environment Variable in CircleCI, CODECOV_TOKEN, and you will find your token directly when you add the repository to CodeCov.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A8lQ4848--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4660/1%2A9QEow4rMNQ3oIcWrVo-m9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A8lQ4848--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4660/1%2A9QEow4rMNQ3oIcWrVo-m9A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As before, in the Project Settings of our Repository in CircleCI, we will add the needed variable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3K3VQSMY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4096/1%2Awc9DhJlo4GVU0FmGCFY6pQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3K3VQSMY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4096/1%2Awc9DhJlo4GVU0FmGCFY6pQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, we need to customize our config.yml adding the Send to codecov step:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And here is the result on CodeCov:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7t0w1LPF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4680/1%2Ay9IVdkQRHzzYPobDFI-Kew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7t0w1LPF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4680/1%2Ay9IVdkQRHzzYPobDFI-Kew.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As latest step, we can also customize the coverage that is run, in order to not run agains the tests folder. What we need to do is simply to add a .coveragerc file, like this one:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;If we open a Pull Request for this change, we can see how CodeCov is directly adding a comment in it, reporting the result of its analyses:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IC_pbI6V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3048/1%2AzFU2w0MuQluBWBCUf0cofQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IC_pbI6V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3048/1%2AzFU2w0MuQluBWBCUf0cofQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configurations of builds for Pull Requests from forks
&lt;/h3&gt;

&lt;p&gt;The last thing I want to show you in this tutorial, is how to properly setup builds also for Pull Request from any fork.&lt;/p&gt;

&lt;p&gt;In the Project Settings, Advanced tab, you have to enable the options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build forked pull requests,&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pass secrets to builds from forked pull requests,&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Only build pull requests,&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auto-cancel redundant builds.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;To end my tutorial, I would like to add two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;first one, you can ensure that these checks are ran before merging any of your Pull Request, creating Branch protections rules in Github:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--twOhtNoV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4240/1%2ANJj0yU95WGqd45-JGLVjxA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--twOhtNoV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4240/1%2ANJj0yU95WGqd45-JGLVjxA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UEymVKGs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3000/1%2AdYNRyjFADwxhzGM814THsA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UEymVKGs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3000/1%2AdYNRyjFADwxhzGM814THsA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;and that you can, for each one of the tools I spoke about today, add a badge in your &lt;a href="https://github.com/fabiogallotti/tutorial_ci/blob/master/README.md"&gt;README.md&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9GFVSleV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2680/1%2Aog65k5llzaFY4ML_W4a5Tg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9GFVSleV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2680/1%2Aog65k5llzaFY4ML_W4a5Tg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;We reached the end of this long tutorial, I hope you enjoyed it and that you will benefit from it!&lt;/p&gt;

</description>
      <category>circleci</category>
      <category>github</category>
      <category>docker</category>
      <category>testautomation</category>
    </item>
  </channel>
</rss>
