Using GitHub Repositories as Helm Registries
Hosting Helm charts can be slightly annoying, as one needs to maintain an extra piece of infrastructure that does practically nothing, or pay for someone else to do it for you.
This article describes a workaround, which uses a standard private repository as a helm chart, which is then accessible via the helm
CLI, ArgoCD, GitHub Actions and more.
To provide some more context, my use case was that of publishing helm charts from private GitHub repositories using GitHub Actions, and that’s what we’re going to look at today.
Quick sidenote: you may alternatively set up a public repository, which allows everyone to get read access to it.
Prerequisites
You’ll need a Personal Access Token to access the helm registry. Check the documentation on how to create one.
Setting Up
We start by creating a simple private repository, where all our charts will be stored.
Create a blank index.yaml
file in the root of the repository (e.g. touch index.yaml
).
Note: We are creating it in the root directory in the
main
branch, but you can also use a subfolder/branch as the registry. You will just need to change the URL when you access the registry, changing the$BRANCH
part of the URL and appending the directory.
You can now add the repository as a helm registry using the command line:
1
helm repo add helm-registry 'https://$TOKEN@raw.githubusercontent.com/$USERNAME/$REPO/$BRANCH'
For example, with a token ghp_xxxxxxxx
, to access the branch main
on the joaomlneto/helm
repository:
1
2
$ helm repo add helm-registry 'https://ghp_xxxxxxxx@raw.githubusercontent.com/joaomlneto/helm/main'
"helm-registry" has been added to your repositories
You can confirm it is added by running helm repo list
:
1
2
3
4
$ helm repo list
NAME URL
…
helm-registry https://ghp_xxxxxxxx@raw.githubusercontent.com/joaomlneto/helm/main
Publishing
I assume you already have a packaged chart. If not, to create a chart you can use
helm create <name>
and to package it you can runhelm package <name>
.
Publishing a chart to the repository requires a small workaround, as we can’t use helm push
. Instead, we’ll just commit the changes manually:
- Clone the repository (e.g.
git clone https://github.com/joaomlneto/helm.git
) - Copy your packaged chart to the repository (
cp <chart.tgz> <repository root>
) - Update the
index.yaml
by runninghelm repo index .
on the root of the repository - Commit and push the changes (
git add . && git commit -m "Add <name> v0.1.0" && git push
)
It may take up to 5 minutes (as contents from rawgithubusercontent.com
are cached), but the chart should then be visible if you run helm repo update
, followed by helm search repo <name>
.
1
2
3
4
5
6
7
8
9
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
…
...Successfully got an update from the "helm-registry" chart repository
…
Update Complete. ⎈Happy Helming!⎈
$ helm search repo testchart
NAME CHART VERSION APP VERSION DESCRIPTION
helm-registry/<name> 0.1.0 1.16.0 A Helm chart for Kubernetes
GitHub Actions
Publishing the artifact via GitHub Actions is the same — you clone the chart repository, copy the packaged chart file, update the index and then commit the changes.
I suggest splitting the chart generation and chart publishing in two separate jobs, and storing your Packages Access Token in an Encrypted Secret.
This is an example job of how you can generate the chart:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
jobs:
…
package:
name: Package Helm Chart
runs-on: ubuntu-latest
outputs:
chart_filename: ${{ steps.chart_filename.outputs.chart_filename }}
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Install Helm
uses: azure/setup-helm@v2.1
with:
version: v3.5.2
- name: Package Helm Charts
run: helm package chart
- id: chart_filename
name: Output Chart Filename
run: echo "::set-output name=chart_filename::$(ls *.tgz)"
- name: Upload Helm Chart Package as Workflow Artifact
uses: actions/upload-artifact@v3
with:
name: ${{ steps.chart_filename.outputs.chart_filename }}
path: ${{ steps.chart_filename.outputs.chart_filename }}
retention-days: 1
if-no-files-found: error
This job will package the chart and upload it as a workflow artifact. This can be later accessed by our publish
job:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
jobs:
…
publish:
name: Publish Helm Chart
runs-on: ubuntu-latest
needs:
- package
steps:
- name: Checkout Chart Repository
uses: actions/checkout@v3
with:
repository: joaomlneto/helm /* CHANGE ME!!! */
token: ${{ secrets.PACKAGES_ACCESS_TOKEN }}
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v2.1
with:
version: v3.5.2
- name: Retrieve Chart Package Workflow Artifact
uses: actions/download-artifact@v3
with:
name: ${{needs.package.outputs.chart_filename }}
- name: Add chart to repository
run: |
helm repo index .
git add .
git commit -m "Add ${{ needs.package.outputs.chart_filename }}"
git push
Conclusion
This article showed that, with very little compromises, we are able to use a vanilla private GitHub repository to emulate a private Helm registry. If something’s amiss, please do let me know!