<?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: Alberto</title>
    <description>The latest articles on Forem by Alberto (@aesadde).</description>
    <link>https://forem.com/aesadde</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%2F244085%2F8a5abb73-19fe-4937-bc9c-de4b203b00d6.jpeg</url>
      <title>Forem: Alberto</title>
      <link>https://forem.com/aesadde</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aesadde"/>
    <language>en</language>
    <item>
      <title>How to deploy a Docusaurus website to K8s</title>
      <dc:creator>Alberto</dc:creator>
      <pubDate>Wed, 04 Aug 2021 13:18:03 +0000</pubDate>
      <link>https://forem.com/aesadde/how-to-deploy-a-docusaurus-website-to-k8s-2p46</link>
      <guid>https://forem.com/aesadde/how-to-deploy-a-docusaurus-website-to-k8s-2p46</guid>
      <description>&lt;p&gt;First, let me give you a bit of background.  &lt;/p&gt;

&lt;p&gt;At my company we're looking for a way to create and share internal documentation with a git and Markdown-based documentation service.  &lt;/p&gt;

&lt;p&gt;The reasons behind these choices are that (1) Markdown is simple to use and all the developers know how to use it; and (2) a git-based service will help us track documentation changes and agree on improvements by using pull requests and "doc reviews" before merging any changes.  &lt;/p&gt;

&lt;p&gt;After some searching around we decided to go with &lt;a href=""&gt;Docusaurus&lt;/a&gt; a static documentation site generator created by Facebook.  &lt;/p&gt;

&lt;p&gt;We really enjoy it since it is based in React Native and once things are set up it is very easy to submit a new doc page or make changes.  &lt;/p&gt;

&lt;p&gt;But when we first started using it we found ourselves with a deployment issue. We wanted to keep the documentation private and didn't want to use any of the services that the docusuarus team propose (Netlify, GitHub Pages, etc.). Instead, we decided to host it on our own "dev" Kubernetes cluster so that we could access it via our proxy and VPN.  &lt;/p&gt;

&lt;p&gt;I didn't find any information on how to do this online, so here are the steps I followed in case you find yourself with the same issue:  &lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I'll assume that you already have a docusuarus website that you can run locally using &lt;code&gt;yarn, yarn build, yarn serve&lt;/code&gt; (or their &lt;code&gt;npm&lt;/code&gt; equivalents).
&lt;/li&gt;
&lt;li&gt;With that out of the way you'll just need to build a docker image:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;12.19&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;alpine&lt;/span&gt;

&lt;span class="nx"&gt;WORKDIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;

&lt;span class="nx"&gt;COPY&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;

&lt;span class="nx"&gt;RUN&lt;/span&gt; &lt;span class="nx"&gt;yarn&lt;/span&gt;

&lt;span class="nx"&gt;RUN&lt;/span&gt; &lt;span class="nx"&gt;yarn&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt;

&lt;span class="nx"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yarn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;serve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push the new image to your preferred docker registry
&lt;/li&gt;
&lt;li&gt;And finally apply a k8s deployment to your cluster. Save and adjust the below &lt;code&gt;yaml&lt;/code&gt; and then simply run &lt;code&gt;kubectl apply -f deployment.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ms-docs&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ms-docs&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ms-docs&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ms-docs&lt;/span&gt;
        &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configMapRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ms-docs&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;my-registry/ms-docs:stable&lt;/span&gt;
        &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Always&lt;/span&gt;
        &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;
          &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
          &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
          &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;
          &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
          &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
        &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;
          &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
          &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
          &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;
          &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;500m"&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;384Mi&lt;/span&gt;
          &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;500m"&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;384Mi&lt;/span&gt;
&lt;span class="s"&gt;--------&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ms-docs&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ms-docs&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Automated Semantic Versions for all projects with semantic-release and Gitlab CI!</title>
      <dc:creator>Alberto</dc:creator>
      <pubDate>Thu, 10 Oct 2019 16:25:57 +0000</pubDate>
      <link>https://forem.com/aesadde/automated-semantic-versions-for-all-projects-with-semantic-release-and-gitlab-ci-4045</link>
      <guid>https://forem.com/aesadde/automated-semantic-versions-for-all-projects-with-semantic-release-and-gitlab-ci-4045</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When software projects start to mature, there usually comes a time when you need to start versioning your releases and publishing Changelogs.&lt;/p&gt;

&lt;p&gt;Most programmers have ways to tackle this issue either by doing things manually and maybe keeping track of a &lt;code&gt;version&lt;/code&gt; file in the project or by using ad-hoc scripts that never quite work.&lt;/p&gt;

&lt;p&gt;At least this has been the case for me. This is why I started searching for solutions that would be agnostic to the type of project and language used and that could be easily added to my CI pipelines.&lt;/p&gt;

&lt;p&gt;After some browsing and experimenting I've found a robust solution with&lt;br&gt;
&lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt; and &lt;a href="https://docs.gitlab.com/ee/ci/" rel="noopener noreferrer"&gt;Gitlab CI&lt;/a&gt; that can be used with any project.&lt;/p&gt;

&lt;p&gt;The rest of this post describes this solution.&lt;/p&gt;
&lt;h2&gt;
  
  
  Semantic Release
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo0lyitpgdtieq4pzjwf0.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo0lyitpgdtieq4pzjwf0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Semantic-release is an &lt;code&gt;npm&lt;/code&gt; tool that automates the process of&lt;br&gt;
generating a new &lt;a href="https://semver.org" rel="noopener noreferrer"&gt;semantic version&lt;/a&gt; and Changelog for your project. All you have to do is adapt your commit messages to follow the &lt;a href="https://gist.github.com/stephenparish/9941e89d80e2bc58a15" rel="noopener noreferrer"&gt;angular commits convention.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tool works by scanning your commits history from the most recent tag&lt;br&gt;
and increments the version number based on the commits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a &lt;code&gt;fix&lt;/code&gt; commit increments the &lt;em&gt;patch&lt;/em&gt; number of the version (the rightmost&lt;br&gt;
number).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a &lt;code&gt;feat&lt;/code&gt; commit increments the &lt;em&gt;minor&lt;/em&gt; number of the version (the middle&lt;br&gt;
number).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a &lt;code&gt;BREAKING CHANGE&lt;/code&gt; commits increments the &lt;em&gt;major&lt;/em&gt; number of the version (the&lt;br&gt;
leftmost number).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, suppose that your latest semantic version is &lt;code&gt;2.1.0&lt;/code&gt; and you had to push a bugfix twith the commit message &lt;code&gt;fix: div by zero&lt;/code&gt;. Your next release would be tagged &lt;code&gt;2.1.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since the tool is simply looking at your commits history, this means that we can use it with any project that uses Git. There are no restrictions on languages or frameworks. Moreover, there are plugins both for GitHub and Gitlab that simplify the process of committing and pushing new tags to the repository of the project as we will see next.&lt;/p&gt;
&lt;h2&gt;
  
  
  Gitlab CI
&lt;/h2&gt;

&lt;p&gt;I'm a big fan of Gitlab's integrated CI pipelines. All you need to do to&lt;br&gt;
automate your workflow is to create a new project on Gitlab and add a&lt;br&gt;
&lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file to the root of your project. Gitlab's own runners will then do its magic.&lt;/p&gt;

&lt;p&gt;Thanks to the Gitlab plugin for semantic-release, creating a CI job for&lt;br&gt;
releasing new tags is as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stages:
 - tag

semantic_release:
  stage: tag
  image: node:8
  variables:
      GITLAB_TOKEN: $ACCESS_TOKEN
  before_script:
      - npm install -g semantic-release @semantic-release/gitlab-config
      - cat $SEM_RELEASE_OPTIONS &amp;gt; .releaserc.yml
  script:
      - semantic-release -e @semantic-release/gitlab-config
  only:
      - master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this there are only two things left to do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You will need to create a personal access token and add it to the CI/CD Variables of your project. For this go to &lt;code&gt;Settings &amp;gt; CI/CD &amp;gt; Variables&lt;/code&gt; and create a new variable named &lt;code&gt;ACCESS_TOKEN&lt;/code&gt;. In the value field put your access token.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Semantic-release has configurable options that the tool can use. These can be set in a &lt;code&gt;package.json&lt;/code&gt; file or a &lt;code&gt;releaserc.yml&lt;/code&gt; file at the root of the project.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I've opted for the second option with a tweak. Rather than keeping the file in my project under version control, I created another &lt;code&gt;CI/CD&lt;/code&gt; variable and pasted the options there.&lt;/p&gt;

&lt;p&gt;To do this copy the below file into a &lt;code&gt;SEM_RELEASE_OPTIONS&lt;/code&gt; variable of type &lt;code&gt;File&lt;/code&gt; in your &lt;code&gt;CI/CD&lt;/code&gt; variables on Gitlab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;branch: master
publish: ['@semantic-release/gitlab']
verifyConditions: ['@semantic-release/gitlab']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, Gitlab will use &lt;code&gt;semantic-release&lt;/code&gt; to publish a new version every time a new commit lands on the &lt;code&gt;master&lt;/code&gt; branch of your project and you can sit back and relax!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>devops</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
