<?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: Scienta</title>
    <description>The latest articles on DEV Community by Scienta (@scienta).</description>
    <link>https://dev.to/scienta</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%2Forganization%2Fprofile_image%2F3749%2F612c9922-f389-4319-a3ca-ca5c09b99da7.png</url>
      <title>DEV Community: Scienta</title>
      <link>https://dev.to/scienta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scienta"/>
    <language>en</language>
    <item>
      <title>Curl commands on helm chart install/upgrade</title>
      <dc:creator> 🐤🥇 Jasper de Jager</dc:creator>
      <pubDate>Sat, 27 Feb 2021 21:51:50 +0000</pubDate>
      <link>https://dev.to/scienta/curl-commands-on-helm-deployment-4i6a</link>
      <guid>https://dev.to/scienta/curl-commands-on-helm-deployment-4i6a</guid>
      <description>&lt;p&gt;Deploying an app with Helm and Kubernetes is great but making it possible to fire a confetti cannon (or anything else you want to do with a curl call) when deploying the app is even better!&lt;/p&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  The challenge
&lt;/h4&gt;

&lt;p&gt;Perform a curl call on every install/update of a helm chart.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  The tools
&lt;/h4&gt;

&lt;p&gt;Kubernetes, Helm, Confetti cannon (optional)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Aaand go!
&lt;/h3&gt;

&lt;p&gt;Ok, we’re not actually going to fire a confetti cannon, disappointing I know and I'm sorry. The actual use case is making a CURL call when a Helm chart gets deployed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Kubernetes
&lt;/h4&gt;

&lt;p&gt;In order to get this to work some sort of container must be deployed alongside the rest of the chart and after some research I ended up with the &lt;a href="https://hub.docker.com/r/curlimages/curl"&gt;curlimages/curl&lt;/a&gt; container.&lt;/p&gt;

&lt;p&gt;Now it’s time to create the Kubernetes workload. After a quick scan of &lt;a href="https://kubernetes.io/docs/concepts/workloads/"&gt;the workloads&lt;/a&gt; of Kubernetes the &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/job/"&gt;job workload&lt;/a&gt; is definitely the way to go here. So the setup so far becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;batch/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;Job&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;job-curl-confetti&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;template&lt;/span&gt;&lt;span class="pi"&gt;:&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;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OnFailure&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;job-curl-confetti&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;curlimages/curl&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sh'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-c'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;curl command here&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a fine way to start the job and perform a CURL call but there are still some issues to tackle like cleaning up the job when it is done and running the job on an upgrade.&lt;/p&gt;

&lt;h4&gt;
  
  
  Helm
&lt;/h4&gt;

&lt;p&gt;This is where Helm comes into action. Helm has a cool option for exactly the issues we're currently running in to named &lt;a href="https://helm.sh/docs/topics/charts_hooks/"&gt;chart hooks&lt;/a&gt;. These hooks can be used to deploy certain Kubernetes workloads and also come with a hook-deletion-policy which can be extremely useful.&lt;/p&gt;

&lt;p&gt;In this case we're going to use the post-install and post-upgrade hooks because we want our Job to run immediately after an install or upgrade. This is achieved by the following changes to the job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;#apiVersion: batch/v1&lt;/span&gt;
&lt;span class="c1"&gt;#kind: Job&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="c1"&gt;#  name: job-curl-confetti&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helm.sh/hook"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post-install,post-upgrade&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helm.sh/hook-delete-policy"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;before-hook-creation&lt;/span&gt;
&lt;span class="c1"&gt;#spec:&lt;/span&gt;
&lt;span class="c1"&gt;#  template:&lt;/span&gt;
&lt;span class="c1"&gt;#    spec:&lt;/span&gt;
&lt;span class="c1"&gt;#      restartPolicy: OnFailure&lt;/span&gt;
&lt;span class="c1"&gt;#      containers:&lt;/span&gt;
&lt;span class="c1"&gt;#        - name: job-curl-confetti&lt;/span&gt;
&lt;span class="c1"&gt;#          image: curlimages/curl&lt;/span&gt;
&lt;span class="c1"&gt;#          command: [ 'sh', '-c']&lt;/span&gt;
&lt;span class="c1"&gt;#          args: &amp;lt;curl command here&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Developer joy (optional)
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Not really optional if you love the job&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything works! But why stop here, why not try to make the chart more accessible for other developers (secretly making it easier to implement the confetti cannon after all). Helm is the right tool for this, let’s make Helm read all files in a directory and create a CURL job executing the curl call in each one of them.&lt;/p&gt;

&lt;p&gt;I'm not going into detail about the implementation of this, that is something for a next blogpost about Helm, but this is the code I eventually ended up with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;- range $path&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$bytes&lt;/span&gt; &lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;= .Files.Glob "jobs/curl/**"&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;span class="pi"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;- $name&lt;/span&gt; &lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;= base (dir $path)&lt;/span&gt; &lt;span class="pi"&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;batch/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;Job&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;job-curl-{{$name}}&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helm.sh/hook"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post-install,post-upgrade&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;helm.sh/hook-delete-policy"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;before-hook-creation&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;template&lt;/span&gt;&lt;span class="pi"&gt;:&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;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OnFailure&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;job-curl-{{$name}}&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;curlimages/curl&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sh'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-c'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
&lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;tpl ($.Files.Get $path) $ | indent  14&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;- end&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helm templates takes all the files in the jobs/curl folder and generates a job for each of them using the helm tpl function so variables form the values file can be used inside the curl call.&lt;/p&gt;

&lt;p&gt;I'm actually pretty proud of it and love the extra mile I put into it. Please let me know what you think!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Get changed files in github actions</title>
      <dc:creator>Kars Barendrecht</dc:creator>
      <pubDate>Wed, 24 Feb 2021 12:22:40 +0000</pubDate>
      <link>https://dev.to/scienta/get-changed-files-in-github-actions-1p36</link>
      <guid>https://dev.to/scienta/get-changed-files-in-github-actions-1p36</guid>
      <description>&lt;p&gt;In the search of a proper way to lint our pull request (changes only). I came across some Github Actions that all require you to &lt;a href="https://github.com/trilom/file-changes-action/blob/a6ca26c14274c33b15e6499323aac178af06ad4b/src/GithubHelper.ts#L127"&gt;share your Github token&lt;/a&gt;. With some knowledge of git I immediately thought, why not solve this with &lt;code&gt;git diff&lt;/code&gt; and some shell commands, thus without the use of a Github token. Git is present by default in the &lt;a href="https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md"&gt;action containers&lt;/a&gt; anyway. Eventually I came up with the following solution. All this requires is a checkout of the codebase, with a step provided by github itself: &lt;a href="https://github.com/actions/checkout"&gt;actions/checkout@v2&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get the commit-sha's to compare
&lt;/h4&gt;

&lt;p&gt;In order to get the commit sha that the pull request was based off, we can use the Github's &lt;a href="https://docs.github.com/en/free-pro-team@latest/actions/reference/context-and-expression-syntax-for-github-actions#contexts"&gt;context&lt;/a&gt;, available in all actions. Here we have acces to &lt;code&gt;github.event.pull_request.base.sha&lt;/code&gt; and &lt;code&gt;github.sha&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Only include files that are still present
&lt;/h4&gt;

&lt;p&gt;To only get the files that are changed and still present we can add the argument &lt;code&gt;--diff-filter=ACMRT&lt;/code&gt;. This will only return files that are added, copied, modified, renamed or changed. In order to get the filenames only we also add &lt;code&gt;--name-only&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remove newlines
&lt;/h4&gt;

&lt;p&gt;In order to get the output in a single line, without newlines, we can pipe the output to &lt;a href="https://man7.org/linux/man-pages/man1/xargs.1.html"&gt;xargs&lt;/a&gt;: &lt;code&gt;COMMAND | xargs&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Filter by filetype (optional)
&lt;/h4&gt;

&lt;p&gt;To get changed files grouped by filetype we can also pipe &lt;a href="https://man7.org/linux/man-pages/man1/grep.1.html"&gt;grep&lt;/a&gt; using a regex as such: &lt;code&gt;COMMAND | grep .ts$&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The finished command
&lt;/h4&gt;

&lt;p&gt;Combining these arguments, we get something like this:&lt;br&gt;
&lt;code&gt;git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep .css$ | xargs&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Using the changed files in an actions workflow
&lt;/h4&gt;

&lt;p&gt;To be able to use the files in another job, we have to use &lt;a href="https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs"&gt;outputs&lt;/a&gt;. Here is a full workflow example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;changedfiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="c1"&gt;# Map a step output to a job output&lt;/span&gt;
    &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.changes.outputs.all}}&lt;/span&gt;
      &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.changes.outputs.ts }}&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Make sure we have some code to diff.&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;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&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;Get changed files&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;changes&lt;/span&gt;
        &lt;span class="c1"&gt;# Set outputs using the command.&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-output name=all::$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | xargs)"&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-output name=ts::$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep .ts$ | xargs)"&lt;/span&gt;
  &lt;span class="na"&gt;lint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="c1"&gt;# require the first job to have ran&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;changedfiles&lt;/span&gt;
    &lt;span class="c1"&gt;# only run there are changed files&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{needs.changedfiles.outputs.ts}}&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo changed files&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;echo ${{needs.changedfiles.outputs.ts}}&lt;/span&gt;

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

&lt;/div&gt;



</description>
      <category>githubactions</category>
      <category>workflow</category>
      <category>github</category>
      <category>changes</category>
    </item>
  </channel>
</rss>
