<?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: Jamie Magee</title>
    <description>The latest articles on DEV Community by Jamie Magee (@jamiemagee).</description>
    <link>https://dev.to/jamiemagee</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%2F256541%2Fafb4887d-89fd-435c-8308-50a210039563.png</url>
      <title>DEV Community: Jamie Magee</title>
      <link>https://dev.to/jamiemagee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jamiemagee"/>
    <language>en</language>
    <item>
      <title>How to host your Helm chart repository on GitHub</title>
      <dc:creator>Jamie Magee</dc:creator>
      <pubDate>Thu, 02 Apr 2020 11:30:52 +0000</pubDate>
      <link>https://dev.to/jamiemagee/how-to-host-your-helm-chart-repository-on-github-3kd</link>
      <guid>https://dev.to/jamiemagee/how-to-host-your-helm-chart-repository-on-github-3kd</guid>
      <description>&lt;p&gt;Since the release of Helm 3, the official &lt;a href="https://github.com/helm/charts" rel="noopener noreferrer"&gt;helm/charts&lt;/a&gt; repository has been deprecated in favour of &lt;a href="https://hub.helm.sh/" rel="noopener noreferrer"&gt;Helm Hub&lt;/a&gt;. While it's great for decentralization and the long term sustainability of the project, I think there's a lot more that is lost. Where is the best place to go for of the expert advice now? Installing Helm now requires you to manually add each repository you use. And there's now some added friction to hosting your Helm charts.&lt;/p&gt;

&lt;p&gt;Thankfully GitHub has all the tools required, in the form of &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt; and &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;, to host a fully automated build pipeline and to host a repository for your Helm charts. Also, we can use some of the tools from the community to ensure our charts are high quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Pages
&lt;/h2&gt;

&lt;p&gt;First you need to go ahead and create a &lt;code&gt;gh-pages&lt;/code&gt; branch in your repository. As I'm writing this there's &lt;a href="https://github.com/helm/chart-releaser-action/issues/10" rel="noopener noreferrer"&gt;an issue&lt;/a&gt; open to do this automatically, but to do it manually you can run the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout --orphan gh-pages
git rm -rf .
git commit -m "Initial commit" --allow-empty
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Once you've done that, you need to enable GitHub Pages in your repository. Go to the settings page on your repository and set the source branch to the &lt;code&gt;gh-pages&lt;/code&gt; branch you just created.&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%2Fi%2Fkb0t8uptr3s35rj1rdfa.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%2Fi%2Fkb0t8uptr3s35rj1rdfa.png" alt="GitHub Pages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you've configured GitHub Pages, it will act as your Helm repository. Next, you need to configure GitHub Actions to publish to there.&lt;/p&gt;
&lt;h2&gt;
  
  
  GitHub Actions
&lt;/h2&gt;

&lt;p&gt;You're going to use GitHub Actions to create two workflows: one for pull requests, and one for commits to master. Your pull request workflow will deal with linting and testing your chart using a collection of automated tooling. While this isn't a direct replacement for the expert advice offered by the Helm community, it's better than nothing. Your master branch workflow will deal with releasing your charts using GitHub pages, meaning you never have to do it manually.&lt;/p&gt;

&lt;p&gt;First up let's look at the pull request workflow.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pull requests
&lt;/h2&gt;

&lt;p&gt;For each pull request in your chart repository, you want to run a series of different validation and linting tools to catch any avoidable mistakes in your Helm charts. To do that, go ahead and create a workflow in your repository by creating a file at &lt;code&gt;.github/workflows/ci.yaml&lt;/code&gt; and add the following YAML to it:&lt;/p&gt;


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



&lt;p&gt;This will run the workflow on any pull request that changes files under the charts directory.&lt;/p&gt;

&lt;p&gt;That's the skeleton of the workflow sorted, next onto the tools that you're going to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chart Testing
&lt;/h3&gt;

&lt;p&gt;The Helm project created Chart Testing, AKA &lt;code&gt;ct&lt;/code&gt;, as a comprehensive linting tool for Helm charts. To use it in your pull request build, you'll go ahead and add the following job:&lt;/p&gt;


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


&lt;p&gt;Where &lt;code&gt;ct.yaml&lt;/code&gt; is:&lt;/p&gt;


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


&lt;p&gt;For a full list of configuration options check out this &lt;a href="https://github.com/helm/chart-testing/blob/master/pkg/config/test_config.yaml" rel="noopener noreferrer"&gt;sample file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;lint&lt;/code&gt; action for Chart Testing is a bit of a catch-all that helps you prevent a lot of potential bugs or mistakes in your charts. That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version checking&lt;/li&gt;
&lt;li&gt;YAML schema validation on &lt;code&gt;Chart.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;YAML linting on &lt;code&gt;Chart.yaml&lt;/code&gt; and &lt;code&gt;values.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Maintainer validation on changed charts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Helm-docs
&lt;/h3&gt;

&lt;p&gt;Helm-docs isn't strictly a linting tool, but it makes sure that your documentation stays up-to-date with the current state of your chart. It requires that you create a &lt;code&gt;README.md.gotmpl&lt;/code&gt; in each chart repository using the &lt;a href="https://github.com/norwoodj/helm-docs#available-templates" rel="noopener noreferrer"&gt;available templates&lt;/a&gt;, otherwise it will create a &lt;code&gt;README.md&lt;/code&gt; for you using a default template.&lt;/p&gt;

&lt;p&gt;To use it as part of your pull request build, you need to add the following job:&lt;/p&gt;


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


&lt;p&gt;Where &lt;code&gt;helm-docs.sh&lt;/code&gt; is:&lt;/p&gt;


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


&lt;p&gt;This runs Helm-docs against each chart in your repository and generates the &lt;code&gt;README.md&lt;/code&gt; for each one. Then, using git, you'll fail the build if there are any differences. This ensures that you can't check in any changes to your charts without also updating the documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kubeval
&lt;/h3&gt;

&lt;p&gt;Next up is Kubeval. It validates the output from Helm against schemas generated from the Kubernetes OpenAPI specification. You're going to add it to your pull request, and use it to validate across multiple different versions of Kubernetes. Add the following job:&lt;/p&gt;


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


&lt;p&gt;Where &lt;code&gt;kubeval.sh&lt;/code&gt; is:&lt;/p&gt;


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


&lt;p&gt;This script is a bit longer, but if you break it down step-by-step it's essentially:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get a list of charts that have been changed between this PR and master branch&lt;/li&gt;
&lt;li&gt;Install Kubeval&lt;/li&gt;
&lt;li&gt;For each chart:

&lt;ol&gt;
&lt;li&gt;Generate the Kubernetes configuration using Helm&lt;/li&gt;
&lt;li&gt;Validatate the configuration using Kubeval&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;You're doing this for each version of Kubernetes you've defined in the job, so if you're using an API that isn't available in all versions, Kubeval will fail the build. This help keep backwards compatibility for all of your charts, and makes sure you're not releasing breaking changes accidentally.&lt;/p&gt;

&lt;p&gt;This doesn't guarantee that the chart will actually install successfully on Kubernetes—but that's where Kubernetes in Docker comes in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kubernetes in Docker (KIND)
&lt;/h3&gt;

&lt;p&gt;Finally you're going to use Chart Testing again to install your Helm charts on a Kubernetes cluster running in the GitHub Actions runner using Kubernetes in Docker (KIND). Like Kubeval, you can create clusters for different versions of Kubernetes.&lt;/p&gt;

&lt;p&gt;KIND doesn't publish Docker images for each version of Kubernetes, so you need to look at the Docker &lt;a href="https://hub.docker.com/r/kindest/node/tags" rel="noopener noreferrer"&gt;image tags&lt;/a&gt;. That's why the Kubernetes versions in this job won't necessarily match the versions used for the Kubeval job.&lt;/p&gt;


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


&lt;p&gt;So you got a temporary Kubernetes cluster, installed your charts on it, and ran any &lt;a href="https://helm.sh/docs/topics/chart_tests/" rel="noopener noreferrer"&gt;helm tests&lt;/a&gt; (that you definitely wrote 🙄). This is the ultimate test of your Helm chart—installing and running it. If this passes, and you merge your pull request, you're ready to release!&lt;/p&gt;

&lt;h2&gt;
  
  
  Releasing
&lt;/h2&gt;

&lt;p&gt;Remember that &lt;code&gt;gh-pages&lt;/code&gt; branch you created earlier? Now you can use it to publish your fully tested Helm chart to.&lt;/p&gt;

&lt;p&gt;You're going to create another GitHub workflow, this time at &lt;code&gt;.github/workflows/release.yaml&lt;/code&gt;. This one is going to be significantly simpler:&lt;/p&gt;


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


&lt;p&gt;It will check out the repository, set the configuration of Git to the user that kicked-off the workflow, and run the chart releaser action. The chart releaser action will package the chart, create a release from it, and update the &lt;code&gt;index.yaml&lt;/code&gt; file in the &lt;code&gt;gh-pages&lt;/code&gt; branch. Simple!&lt;/p&gt;

&lt;p&gt;But one thing you still need to do is create a secret in your repository, &lt;code&gt;CR_TOKEN&lt;/code&gt;, which contains a GitHub &lt;a href="https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line#creating-a-token" rel="noopener noreferrer"&gt;personal access token&lt;/a&gt; with &lt;code&gt;repo&lt;/code&gt; scope. This is due to a &lt;a href="https://github.community/t5/GitHub-Actions/Github-action-not-triggering-gh-pages-upon-push/m-p/31266/highlight/true#M743" rel="noopener noreferrer"&gt;GitHub Actions bug&lt;/a&gt;, where GitHub Pages is not deployed when pushing from GitHub Actions.&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%2Fi%2Fyhejethagx3q3u8k3n0m.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%2Fi%2Fyhejethagx3q3u8k3n0m.png" alt="GitHub Secrets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once that's all configured, any time a change under the charts directory is checked in, like from a pull request, your Github workflow will run and your charts will be available almost instantly!&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;From here you'll want to add your repository to Helm so you can use it, and share it on &lt;a href="https://hub.helm.sh/" rel="noopener noreferrer"&gt;Helm Hub&lt;/a&gt; so others can too. For the former, you'll need to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add renovate https://&amp;lt;username&amp;gt;.github.io/&amp;lt;repository&amp;gt;/
helm repo update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for the latter, the Helm project have written &lt;a href="https://github.com/helm/hub/blob/master/Repositories.md" rel="noopener noreferrer"&gt;a comprehensive guide&lt;/a&gt; that I couldn't possibly top.&lt;/p&gt;

&lt;p&gt;If you want to see all these pieces working together checkout the &lt;a href="https://github.com/renovatebot/helm-charts" rel="noopener noreferrer"&gt;renovatebot/helm-charts&lt;/a&gt; repository, or our page on &lt;a href="https://hub.helm.sh/charts/renovate/renovate" rel="noopener noreferrer"&gt;Helm Hub&lt;/a&gt;. And if you would like some help please reach out to me on Twitter at &lt;a href="https://twitter.com/Jamie_Magee" rel="noopener noreferrer"&gt;@Jamie_Magee&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>helm</category>
      <category>github</category>
    </item>
    <item>
      <title>7 tips for converting C# code to async/await</title>
      <dc:creator>Jamie Magee</dc:creator>
      <pubDate>Mon, 16 Mar 2020 13:24:52 +0000</pubDate>
      <link>https://dev.to/jamiemagee/7-tips-for-converting-c-code-to-async-await-2557</link>
      <guid>https://dev.to/jamiemagee/7-tips-for-converting-c-code-to-async-await-2557</guid>
      <description>&lt;p&gt;Over the past year I've moved from working mainly in Java, to working mainly in C#. To be honest, Java and C# have more in common than not, but one of the major differences is async/await. It's a really powerful tool if used correctly, but also a very quick way to shoot yourself in the foot.&lt;/p&gt;

&lt;p&gt;Asynchronous programming looks very similar to synchronous programming. However, there are some core concepts which need to be understood in order to form a proper mental model when converting between synchronous and asynchronous programming patterns.&lt;/p&gt;

&lt;p&gt;Here are some of the most common ones I've come across.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming
&lt;/h2&gt;

&lt;p&gt;Method names must use the suffix Async when returning a &lt;code&gt;Task&lt;/code&gt; or &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt;. Consistency is key as the &lt;code&gt;Async&lt;/code&gt; suffix provides not only a mental signal to the caller that the await keyword should be used, but also provides a consistent naming convention.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Return types
&lt;/h2&gt;

&lt;p&gt;Every async method returns a &lt;code&gt;Task&lt;/code&gt;. Use &lt;code&gt;Task&lt;/code&gt; when there is no specific result for the method, which is synonymous with &lt;code&gt;void&lt;/code&gt;. Use &lt;code&gt;Task&amp;lt;T&amp;gt;&lt;/code&gt; when a return value is required.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Parameters
&lt;/h2&gt;

&lt;p&gt;There is not a way for the compiler to manage &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;out&lt;/code&gt; parameters. (That's a topic for another time.) When multiple values need to be returned you should either use custom objects or a &lt;code&gt;Tuple&lt;/code&gt;.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Delegates
&lt;/h2&gt;

&lt;p&gt;Following up on the lack of the &lt;code&gt;void&lt;/code&gt; return type, no async method should be defined as an &lt;code&gt;Action&lt;/code&gt; variant. When accepting a delegate to an asynchronous method, the asynchronous pattern should be propagated by accepting &lt;code&gt;Func&amp;lt;Task&amp;gt;&lt;/code&gt; or &lt;code&gt;Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Virtual methods
&lt;/h2&gt;

&lt;p&gt;In asynchronous programming there is no concept of a &lt;code&gt;void&lt;/code&gt; return type, as the basis of the model is that each method returns a mechanism for signaling completion of the asynchronous work. When converting base classes which have empty implementations or return constant values, the framework provides methods and helpers to facilitate the pattern.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Interfaces
&lt;/h2&gt;

&lt;p&gt;Like delegates, interfaces should always be declared async which ensures an async-aware model throughout the stack.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Mocks
&lt;/h2&gt;

&lt;p&gt;In certain cases, mostly unit test mocks, you may find the need to implement interfaces without having any reason to actually perform any asynchronous calls. In these specific cases it is OK to feign asynchronous execution using &lt;code&gt;Task.CompletedTask&lt;/code&gt; or &lt;code&gt;Task.FromResult&amp;lt;T&amp;gt;(T result)&lt;/code&gt;.&lt;/p&gt;


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


&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Overall asynchronous programming is much better for performance, but requires a slightly different mental model. I hope these tips help!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>async</category>
      <category>await</category>
    </item>
    <item>
      <title>Automated Dependency Updates</title>
      <dc:creator>Jamie Magee</dc:creator>
      <pubDate>Wed, 23 Oct 2019 18:12:24 +0000</pubDate>
      <link>https://dev.to/jamiemagee/automated-dependency-updates-3bib</link>
      <guid>https://dev.to/jamiemagee/automated-dependency-updates-3bib</guid>
      <description>&lt;p&gt;At &lt;a href="https://copenhagenjs.dk"&gt;CopenhagenJS&lt;/a&gt; in August I was able to share my work on &lt;a href="https://renovatebot.com/"&gt;Renovate&lt;/a&gt;—a universal dependency update tool—and how you can use it to save time and improve security in software projects.&lt;/p&gt;

&lt;p&gt;If you want to find out more about Renovate you can find us &lt;a href="https://github.com/renovatebot/renovate"&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>techtalks</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
