Auto Docs, Test And Release A Helm Chart With GitHub Actions

TL;DR Code
-> https://github.com/dirien/minecraft-prometheus-exporter
Motivation
Currently, I am working on a Helm chart for my Minecraft Prometheus exporter. Nothing special on this task.
But now I want to put as much automation into it, as possible.
Automated Documentation With helm-docs

The helm-docs tool auto-generates documentation from helm charts into markdown files. That is very cool, as we don't need to take care to keep the documentation manually in up to date with the values.yaml
To do this, we create in the chart directory a README.md.gotmpl file, this contains the template to render the final README.md file with the informations from your Helm chart values.
Here is the example of my file:
# Minecraft Exporter for Prometheus

{{ if .Type }} {{ end }}
{{ if .AppVersion }} {{ end }}




## Description
{{ template "chart.description" . }}
## Usage
<fill out>
{{ template "chart.valuesSection" . }}
{{ template "chart.homepageLine" . }}
{{ template "chart.sourcesSection" . }}
{{ template "chart.maintainersSection" . }}
helm-docs has plenty of predefined template functions for you to use, on top you can also use the variables directly. Throw in your static parts and you get an awesome automated documentations.
Hint: To get the values table rendered with proper default values, you need to add # -- description
image:
# -- The docker image repository to use
repository: ghcr.io/dirien/minecraft-exporter
# -- The docker image tag to use
tag: ''
# -- The docker image pull policy
pullPolicy: IfNotPresent
You can add # -- @default defaut text
image:
# -- The docker image repository to use
repository: ghcr.io/dirien/minecraft-exporter
# -- The docker image tag to use
# @default Chart version
tag: ''
# -- The docker image pull policy
pullPolicy: IfNotPresent
Now you have to option to create a pre-commit hook, so everytime you change a specified file in your .pre-commit-hooks.yaml the README.md file gets re-rendered
Let me shortly explain pre-commit
How to configure the pre-commit hook
I am going to use pre-commit. Check the docs on how to install it.
pre-commit is a multi-language package manager for pre-commit hooks. You specify a list of hooks you want and pre-commit manages the installation and execution of any hook written in any language before every commit.
I created a git-hook folder with the helm-docs.sh. This file will be called, from pre-commit
#!/usr/bin/env bash
set -e
if ! command -v helm-docs > /dev/null 2>&1; then
echo "Please install helm-docs to run the pre-commit hook! https://github.com/norwoodj/helm-docs#installation"
exit 1
fi
helm-docs "${@}"
in the .pre-commit-config.yaml you can set the args to pass the the git-hook/helm-docs.sh script.
repos:
- repo: https://github.com/dirien/minecraft-prometheus-exporter
rev: v0.10.0
hooks:
- id: helm-docs
args:
- --template-files=README.md.gotmpl
The content of the .pre-commit-hooks.yaml defines on which files, the git-hook/helm-docs.sh should be called.
And of course the relation between the id of the .pre-commit-config.yaml
- id: helm-docs
args: []
description: Uses 'helm-docs' to create documentation from the Helm chart's 'values.yaml' file, and inserts the result into a corresponding 'README.md' file.
entry: git-hook/helm-docs.sh
files: (README\.md\.gotmpl|(Chart|requirements|values)\.yaml)$
language: script
name: Helm Docs
require_serial: true
Hint: During the start, you will not have a remote location with your .pre-commit-hooks.yaml so you can test your hook via this command:
pre-commit install
pre-commit try-repo . helm-docs --verbose --all-files
Otherwise, you can just call:
pre-commit install
pre-commit install-hooks
The only downside of this approach is: If someone is contributing to your
helmchart you need to rely on, that has thepre-commithook cli installed.
GitHub Action
So I will add the generation of the helm-docs to my CI pipeline called chart-publish
name: chart-publish
...
env:
HELM_DOCS_VERSION: "1.7.0"
...
- name: install helm-docs
run: |
cd /tmp
wget https://github.com/norwoodj/helm-docs/releases/download/v${{env.HELM_DOCS_VERSION}}/helm-docs_${{env.HELM_DOCS_VERSION}}_Linux_x86_64.tar.gz
tar -xvf helm-docs_${{env.HELM_DOCS_VERSION}}_Linux_x86_64.tar.gz
sudo mv helm-docs /usr/local/sbin
- name: run helm-docs
run: |
helm-docs -t README.md.gotmpl -o README.md
...
You can find more information here -> https://github.com/norwoodj/helm-docs
Chart Testing & Linting With ct

ct is the tool for testing Helm charts. It automatically detects if a charts changed against the target branch we define.
We need to create a config file called ct-lint.yaml under the .github/configs with following content:
remote: origin
target-branch: main
chart-dirs:
- charts
helm-extra-args: "--timeout 600s"
validate-chart-schema: true
validate-chart-values: true
validate-maintainers: true
validate-yaml: true
exclude-deprecated: true
excluded-charts: []
This are some properties for the cli, so we don't need to pass them via flag. On addition, I created lintconf.yamlunder the same folder, which contains some rules for yamllint.
yamllint does not only check for syntax validity, but for weirdnesses like key repetition and cosmetic problems such as lines length, trailing spaces, indentation, etc.
---
rules:
braces:
min-spaces-inside: 0
max-spaces-inside: 0
min-spaces-inside-empty: -1
max-spaces-inside-empty: -1
..... snip .....
without
check-multi-line-strings: false
key-duplicates: enable
line-length: disable # Lines can be any length
new-line-at-end-of-file: enable
new-lines:
type: unix
trailing-spaces: enable
truthy:
level: warning
And then you can run:
ct lint --config .github/configs/ct-lint.yaml --lint-conf .github/configs/lintconf.yaml
to execute the linting.
As mentioned before, ct needs some additional tools like Helm, Git (2.17.0 or later), Yamllint, Yamale, Kubectl so it is better to use the ct container, if you want to test the linting localy:
docker container run --rm -v $(pwd):/workspace -ti quay.io/helmpack/chart-testing:v3.5.0
Next step is the testing of the chart. If you have a local kubernetes cluster you can call:
ct install --config ./.github/configs/ct-lint.yaml
It will install the chart and if everything works fine instantly deletes it.
Installing charts...
------------------------------------------------------------------------------------------------------------------------
Charts to be processed:
------------------------------------------------------------------------------------------------------------------------
minecraft-exporter => (version: "0.1.0", path: "charts/minecraft-exporter")
------------------------------------------------------------------------------------------------------------------------
Installing chart 'minecraft-exporter => (version: "0.1.0", path: "charts/minecraft-exporter")'...
Creating namespace 'minecraft-exporter-hwe920t1yv'...
namespace/minecraft-exporter-hwe920t1yv created
NAME: minecraft-exporter-hwe920t1yv
....
========================================================================================================================
Deleting release 'minecraft-exporter-hwe920t1yv'...
release "minecraft-exporter-hwe920t1yv" uninstalled
W0122 21:56:16.272288 69990 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
Deleting namespace 'minecraft-exporter-hwe920t1yv'...
namespace "minecraft-exporter-hwe920t1yv" deleted
Namespace 'minecraft-exporter-hwe920t1yv' terminated.
------------------------------------------------------------------------------------------------------------------------
✔︎ minecraft-exporter => (version: "0.1.0", path: "charts/minecraft-exporter")
------------------------------------------------------------------------------------------------------------------------
All charts installed successfully
Of course you can call both actions in one command with ct lint-and-install
Finally we can create a GitHub action to run during a PR and test and lint our Helm chart.
---
name: ct-linting-and-testing
on: pull_request
jobs:
chart-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Helm
uses: azure/setup-helm@v1
with:
version: v3.6.3
- name: Set up python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Setup Chart Linting
id: lint
uses: helm/chart-testing-action@v2.2.0
- name: List changed charts
id: list-changed
run: |
## If executed with debug this won't work anymore.
changed=$(ct --config ./.github/configs/ct-lint.yaml list-changed)
charts=$(echo "$changed" | tr '\n' ' ' | xargs)
if [[ -n "$changed" ]]; then
echo "::set-output name=changed::true"
echo "::set-output name=changed_charts::$charts"
fi
- name: Run chart-testing (lint)
run: ct lint --debug --config ./.github/configs/ct-lint.yaml --lint-conf ./.github/configs/lintconf.yaml
- name: Create kind cluster
uses: helm/kind-action@v1.2.0
if: steps.list-changed.outputs.changed == 'true'
- name: Run chart-testing (install)
run: ct install --config ./.github/configs/ct-lint.yaml
if: steps.list-changed.outputs.changed == 'true'
We use the predefined GitHub action for installing the ct CLI tool. So we dont need to take care about the additional tools ct needs.

On top as you can see, we start a Kind cluster to install and test the helm chart.
You can find more information here -> https://github.com/helm/chart-testing
Releasing the Chart with cr

The last part, is the quickest. We use cr as tool here. cr is a tool designed to help us to release a helm chart and connect a GitHub releases with the index.yaml and upload this to the GitHub pages.
We just need to add in our chart-publish following task at as an additional task:
---
name: chart-publish
...
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.2.1
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
...
That's it.
You should be now apple to install your chart via your GitHub pages url.
helm repo add minecraft-exporter https://dirien.github.io/minecraft-prometheus-exporter
helm repo update
helm install minecraft-exporter minecraft-exporter/minecraft-exporter --version 0.1.2
You can find more information here -> https://github.com/helm/chart-releaser
Result on ArtifactHub
The End

Resources
- https://github.com/norwoodj/helm-docs
- https://github.com/helm/chart-testing
- https://github.com/helm/chart-releaser
- https://github.com/marketplace/actions/helm-chart-testing
- https://github.com/adrienverge/yamllint




