Helm: manually publishing Helm repo on Github using chart-releaser

The only requirement for a public Helm chart repository is that it exposes a URL named “index.yaml”.   So by adding a file named “index.yaml” to source control and enabling Github Pages to serve the file over HTTPS, you have the minimal basis for a public Helm chart repository.

The backing Chart content (.tgz) can also be uploaded as a Github Release, conveniently allowing us to host the entire solution in our Github repository.

The ‘cr‘ (chart-releaser) tool wraps up the logic of managing index.yaml and the backing chart .tgz files, allowing us to focus on chart development.

If you would rather use Github Actions to automatically run chart-releaser on push events, read my article here.

Prerequisites

# download, extract, and copy binary to PATH
cd ~
wget https://github.com/helm/chart-releaser/releases/download/v1.6.0/chart-releaser_1.6.0_linux_amd64.tar.gz
tar xfz chart-releaser_1.6.0_linux_amd64.tar.gz cr
sudo mv cr /usr/local/bin/

Helm Chart for publishing

This article (and the default tool settings) assume your Helm Charts are located in the ‘charts’ folder of the github repository.

If you do not have a helm chart in the ‘charts’ folder yet, follow these instructions to create a simple nginx Helm Chart.

# substitute these values for your own Github repository
git clone https://github.com/fabianlee/helm-chart-published-to-github.git
cd helm-chart-published-to-github

# setup variables
repo_name="${PWD##*/}"
owner_name=$(git remote -v | grep origin | head -n1 | grep -Po ":\K[^/]*")
echo "Going to configure $repo_name owned by '$owner_name' as a Helm Chart repository"

# create standard 'charts' folder
mkdir -p charts
cd charts

# create simple 'nginx' sample Chart
helm create nginx
cd ..

# dry-run of chart, shows manifests that would be used during release
helm install --dry-run mynginx1 charts/nginx

Enable Github Pages feature

By creating a new branch named ‘gh-pages’, it will automatically enable Github Pages and our ability to serve content from the source code repository at ‘https://<owner>.github.io/<repoName>’.

Run the following commands to create a fresh branch named ‘gh-pages’.

# get current branch
git branch
main_branch=$(git branch --show-current)

# create fresh 'gh-pages' branch, standard for Github Pages
git switch --orphan gh-pages
git commit -a -m "initial commit of gh-pages" --allow-empty
git push -u origin gh-pages

# go back to branch
git checkout $main_branch

Verify that Github Pages is enabled by going to your repository > Settings > Pages.  It should report “Your site is live”, on the branch “gh-pages”.

Generate Chart .tgz files

We will have the chart-releaser utility generate the .tgz files for each Chart version first.  This is because the .tgz and its calculated hash are required in the next step when generating index.yaml entries.

# token used for Github API authentication, per prerequisites
CR_TOKEN=<githubPAT>

# generate Chart tgz files
git checkout $main_branch
helm package charts/* -d .cr-release-packages
# verify 'nginx-0.1.0.tgz' exists
ls -l .cr-release-packages/

# upload .tgz via API as Github Release
cr upload -r $repo_name -o $owner_name --skip-existing -t $CR_TOKEN

This can be validated from the Github web UI, in the ‘Releases’ section of your repository.

Generate index.yaml

Now that we have the .tgz generated, we can use these files to populate the entries for index.yaml.

# switch to branch that Github Pages serves
git checkout gh-pages

# generate entries for Chart releases
cr index -i ./index.yaml -r $repo_name -o $owner_name

# show entries generated
cat index.yaml

# commit and push, making it publicly visible
git add index.yaml
git commit -m "updated index.yaml" index.yaml
git push


# wait a few seconds, then validate content can be retrieved
sleep 30
curl https://$owner_name.github.io/$repo_name/index.yaml

Validate from Helm client

With our index.yaml and Chart .tgz files fully published, it is a fully-functioning public Helm Repository.

# current repo list
helm repo list

# add our new Github repo
helm repo add $repo_name https://$owner_name.github.io/$repo_name
helm repo list

# show chart versions available (only 0.1.0)
helm search repo -l $repo_name

# show general chart information
chart_name=nginx
full_chart_name=$repo_name/$chart_name
helm show chart $full_chart_name

# values for release
release_name=mynginx1
release_ns=default

# dry run of Chart, does not touch cluster
version=0.1.0
helm install --dry-run $release_name $full_chart_name --version $version -n $release_ns

Note that we only did a dry-run of the chart release in the interest of simplicity.  Nothing was installed into the Kubernetes cluster.

Versioning the Chart

Helm Charts are continually enhanced, so let’s go through the day-2 task of versioning this Helm Chart.

# make sure we are on charts branch
git checkout $main_branch

# increment to new version (0.1.0 was original)
new_version=0.2.0
sed -i "s/^version: .*/version: $new_version/" charts/nginx/Chart.yaml

# generate new .tgz for new version
helm package charts/* -d .cr-release-packages
# validate new .tgz exists
ls -l .cr-release-packages/

# upload new .tgz as Github Release
cr upload -r $repo_name -o $owner_name --skip-existing -t $CR_TOKEN

# generate additional index entry for new version
git checkout gh-pages
cr index -i ./index.yaml -r $repo_name -o $owner_name
git commit -m "updated index.yaml for $new_version" index.yaml
git push

# back to chart branch
git checkout $main_branch

Validate new Chart version using Helm client

You could validate the new nginx-0.2.0.tgz file is found in the ‘Releases’ section of the Github web UI, and index.yaml has been updated with entries for both version ‘0.1.0’ and ‘0.2.0’.  But instead let’s use the Helm client to validate.

# show chart versions available (still only 0.1.0)
helm search repo -l $repo_name

# do repo update
helm repo update $repo_name
# check available versions again (now both 0.1.0 and 0.2.0)
helm search repo -l $repo_name

# dry run of new Chart version
version=0.2.0
helm install --dry-run $release_name $full_chart_name --version $version -n $release_ns

 

REFERENCES

Markus Lippert, Host Helm charts via GitHub with Chart Releaser

Jamie Magee, how to host your Helm chart repository on GitHub

Anup Dubey, How to host Helm Chart repository on Github

github chart-releaser

github chart-releaser-action for Github Actions

colinwilson.uk, signing helm charts with chart-releaser-action

Piotr Minkowski, shows Circle CI raw ‘cr’ commands for generating helm chart

helm.sh, shows how to use Github workflow with chart-releaser-action (left out required ‘write’ permissions for contents)

Github, Github Pages enablement

Helm chart provenance