<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rail</title>
    <description>The latest articles on Forem by Rail (@rhamdeew).</description>
    <link>https://forem.com/rhamdeew</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%2F348109%2Fd2926c57-6196-411b-af41-643936b89480.jpeg</url>
      <title>Forem: Rail</title>
      <link>https://forem.com/rhamdeew</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rhamdeew"/>
    <language>en</language>
    <item>
      <title>How to cache dependencies in GitLab</title>
      <dc:creator>Rail</dc:creator>
      <pubDate>Thu, 08 Apr 2021 10:06:49 +0000</pubDate>
      <link>https://forem.com/rhamdeew/how-to-cache-dependencies-in-gitlab-33p0</link>
      <guid>https://forem.com/rhamdeew/how-to-cache-dependencies-in-gitlab-33p0</guid>
      <description>&lt;p&gt;Hi everybody!&lt;br&gt;
Today I want to tell you about my experience of using GitLab CI dependency caching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is it needed
&lt;/h3&gt;

&lt;p&gt;I have a small pet project where I usually experiment with new technologies and approaches. The repository of this project is stored in GitLab. There I configured CI/CD tasks for testing and deploying a project.&lt;/p&gt;

&lt;p&gt;CI-task with testing usually completed in 2 minutes. But every time I thought about what actions are being performed in this time. An example is installing Python dependencies.&lt;/p&gt;

&lt;p&gt;On the one hand, this guarantees reproducible builds (let's say hello to leftpad and mimemagick 😄).&lt;/p&gt;

&lt;p&gt;But on the other hand, these actions are performed every time when I push changes to the repository. And that's just a pet project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's try to enable caching 🤟&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is an official GitLab documentation about CI caching with examples - &lt;a href="https://docs.gitlab.com/ee/ci/caching" rel="noopener noreferrer"&gt;https://docs.gitlab.com/ee/ci/caching&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project on which I tested CI-caching is written on Django and uses poetry for dependency and virtual environments management.&lt;/p&gt;

&lt;h3&gt;
  
  
  What .gitlab-ci.yml looked like before the changes
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tests&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;

&lt;span class="na"&gt;tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tests&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;python:3.7-slim&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apt-get update -qy &amp;amp;&amp;amp; apt-get install -y build-essential&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip --no-cache-dir install poetry&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;poetry config virtualenvs.create &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="s"&gt; &amp;amp;&amp;amp; poetry install --no-root&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sed 's/#DATABASE_URL/DATABASE_URL/g' telega/.env.example &amp;gt; telega/.env&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;coverage run --source='.' manage.py test &amp;amp;&amp;amp; coverage report -m&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Here We install Debian packages and then install poetry through pip and install project dependencies with poetry.&lt;/p&gt;

&lt;h3&gt;
  
  
  How .gitlab-ci.yml looks like after the changes
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tests&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deploy&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;PIP_CACHE_DIR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$CI_PROJECT_DIR/.cache/pip"&lt;/span&gt;

&lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;poetry.lock&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.gitlab-ci.yml&lt;/span&gt;
    &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${CI_JOB_NAME}&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;.venv&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.cache/pip&lt;/span&gt;

&lt;span class="na"&gt;tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tests&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;python:3.7-slim&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apt-get update -qy &amp;amp;&amp;amp; apt-get install -y build-essential&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip install poetry&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;poetry config virtualenvs.in-project &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;poetry install --no-root&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sed 's/#DATABASE_URL/DATABASE_URL/g' telega/.env.example &amp;gt; telega/.env&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;poetry run coverage run manage.py test &amp;amp;&amp;amp; poetry run coverage report -m&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;I added some settings to tell pip and poetry where packages should be stored. Then I added 'cache' section and set poetry.lock and .gitlab-ci.yml files as key for cache. &lt;/p&gt;

&lt;p&gt;This means that if at least one of the files is changed then packages should be installed from PyPI, but in another case will be used cached directories with already installed packages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;CI-task running time is decreased from 2 minutes to 1 minute. Of course, the checking and unpacking cache operation was added, but it's still faster than installing dependencies from PyPI.&lt;/p&gt;

&lt;p&gt;In the screenshot with the task logs, we can see how pip use the cache.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnmkv0gf65zea3bb8oy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnmkv0gf65zea3bb8oy7.png" alt="GitLab CI job logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here We can see that the poetry did not install anything new.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fauyoz62so8tah4ustn3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fauyoz62so8tah4ustn3k.png" alt="GitLab CI job logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cache dependencies in GitLab CI/CD are a powerful tool for faster-running tasks and the economy of resources.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>python</category>
      <category>poetry</category>
      <category>ci</category>
    </item>
    <item>
      <title>Setup your own OpenVPN in 10 minutes </title>
      <dc:creator>Rail</dc:creator>
      <pubDate>Sat, 27 Mar 2021 09:39:00 +0000</pubDate>
      <link>https://forem.com/rhamdeew/setup-your-own-openvpn-in-10-minutes-5g8p</link>
      <guid>https://forem.com/rhamdeew/setup-your-own-openvpn-in-10-minutes-5g8p</guid>
      <description></description>
      <category>docker</category>
      <category>ansible</category>
      <category>openvpn</category>
      <category>centos</category>
    </item>
    <item>
      <title>Setup your own OpenVPN in 10 minutes</title>
      <dc:creator>Rail</dc:creator>
      <pubDate>Tue, 23 Mar 2021 18:24:31 +0000</pubDate>
      <link>https://forem.com/rhamdeew/setup-your-own-openvpn-in-10-minutes-3c4h</link>
      <guid>https://forem.com/rhamdeew/setup-your-own-openvpn-in-10-minutes-3c4h</guid>
      <description>&lt;p&gt;Hi everyone!&lt;br&gt;
In this video, I show you how to start your own VPN server based on CentOS 8 in 10 minutes. The video shows the practical use of Ansible, Docker and OpenVPN.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I tried for the first time to record a screencast and provide it with a text description in English. I would be happy to receive comments and suggestions. Thanks for your attention!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KApzBc6V6HY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Ansible Playbook
&lt;/h3&gt;

&lt;p&gt;Link to Ansible Playbook - &lt;a href="https://github.com/rhamdeew/ansible-docker-compose-openvpn-secure-centos8"&gt;https://github.com/rhamdeew/ansible-docker-compose-openvpn-secure-centos8&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The playbook uses roles from &lt;a href=""&gt;Jeff Geerling&lt;/a&gt; (geerlingguy.repo-epel, geerlingguy.security, geerlingguy.pip, geerlingguy.docker)&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker-compose repository
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/rhamdeew/docker-compose-openvpn"&gt;https://github.com/rhamdeew/docker-compose-openvpn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This repo based on &lt;a href="https://github.com/kylemanna/docker-openvpn"&gt;kylemanna/docker-openvpn&lt;/a&gt; but have Makefile with useful commands for comfortable OpenVPN setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  No time to watch the video. How to setup?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tunnelblick (&lt;a href="https://tunnelblick.net/downloads.html%E2%80%8B"&gt;https://tunnelblick.net/downloads.html​&lt;/a&gt;) – VPN-client for macOS&lt;/li&gt;
&lt;li&gt;Ansible (Homebrew) – IT automation tool&lt;/li&gt;
&lt;li&gt;Tmux (Homebrew) – terminal multiplexer (optional)&lt;/li&gt;
&lt;li&gt;Alacritty (Homebrew) – fast terminal emulator (optional)&lt;/li&gt;
&lt;li&gt;DigitalOcean account - hosting provider with fast VPS provisioning (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Screencast contains 4 steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate SSH-key pair, create a virtual server with CentOS 8&lt;/li&gt;
&lt;li&gt;Clone and run Ansible Playbook for basic server setup and installing Docker&lt;/li&gt;
&lt;li&gt;Quickly configure OpenVPN settings and start Docker-container&lt;/li&gt;
&lt;li&gt;Add client-config to VPN-client and connect&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ansible</category>
      <category>docker</category>
      <category>centos</category>
    </item>
  </channel>
</rss>
