Setup Continuous Integration for Helm chart

Helm is a package manager for Kubernetes that allows developers and operators to easily package, configure, and deploy applications and services onto Kubernetes clusters.

Setup Continuous Integration for Helm chartSetup Continuous Integration for Helm chart

Helm is now an official Kubernetes project and is part of the Cloud Native Computing Foundation, a non-profit Linux Foundation that supports Open Source projects in and around the Kubernetes ecosystem.

In this tutorial, we will set up a continuous integration of the Helm chart. We will package the Helm chart with the help of CI tools like (Travis, Jenkins), and push it to chart registries like (Harbor, Chartmuseum).


  • Registry to store Helm like Harbor or Chartmuseum
  • Understanding of Helm and any of the CI platforms (Travis, Jenkins, circle, CI)
  • A Git repository to maintain version control of helm chart

I am going to use Travis as a CI platform and Harbor as a Helm registry to host the helm.

As I choose Travis here, .travis.yml consists of the job lifecycle. Let’s write job cycle for the helm chart.

Lifecycle 1:

Choose the base language as Python

language: python

We need to have some environment variables so that we can update whenever there’s a new version of the Helm release or change of the registry URL.

Here is the list of a variable that we’ll need:

  1. HELM_URL= (this is the URL where we can download the helm package)
  2. HELM_TGZ=helm-v2.4.2-linux-amd64.tar.gz (this is the Helm tar filename)
  3. REPO_DIR=/home/travis/build/inyee786/test-helm (this is the path where Travis keep Git folder)
  4. YAMLLINT_VERSION=1.8.1 (this is yamllint version which is used to check lint of file)
  5. HARBOR_CHART_URL= (change this according to your chart registry url{harbor or Chartmuseum}
  6. HARBOR_PROJECT_NAME=maya (this is the Harbor project name, where we will store the chart)
  7. CHART_FOLDER=charts (this is the folder name, where we can keep the Helm charts)

It looks like this

   - HELM_URL=
   - HELM_TGZ=helm-v2.4.2-linux-amd64.tar.gz
   - REPO_DIR=/home/travis/build/inyee786/test-helm
   - CHART_FOLDER=charts

We need some private variables, where we can store the credentials and push it to the Helm registry (Harbor has an excellent feature where we can have bot user, and you can use the bot credential). All we have to feed is-


Inside Travis, go to (settings > Environment Variables) to set the private env

Environment variables

Lifecycle 2 :

Install the Prerequisites to Set up a CI environment to build and check the YAML lint.

Download helm and untar the chart after downloading

  • wget ${HELM_URL}/${HELM_TGZ}
  • tar xzfv ${HELM_TGZ}
  • PATH=`pwd`/linux-amd64/:$PATH

Initialize the helm client and update the helm repo

  • Helm init — client-only
  • Helm repo update

Install helm plugin to push chart on the registry

Install yamllint python package to check the lint

  • sudo pip install yamllint==”${YAMLLINT_VERSION}”

It looks like the below config

# Installing Helm
 - wget ${HELM_URL}/${HELM_TGZ}
 - tar xzfv ${HELM_TGZ}
 - PATH=`pwd`/linux-amd64/:$PATH
 - helm init --client-only
 # helm plugin to push helm chart
 - helm plugin install --version v0.7.1
 # Installing pip deps
 - sudo pip install yamllint=="${YAMLLINT_VERSION}"
 - helm repo update

Lifecycle 3 :

Before going further to build a chart, we need to run some script to check the lint in the chart and Travis file. It is a good practice to check the lint

Check the Helm lint of all Helm chart

  • For dir in `ls ${REPO_DIR}/${CHART_FOLDER}`; do
    helm lint ${REPO_DIR}/${CHART_FOLDER}/$dir
    if [ $? != 0 ]; then
    travis_terminate 1

To check the YAML lint for travis.yml, chart.yaml and value.yaml, we use the yamllint python package. We need the rule to check the lint.

  • yamllint -c .yamllint.yml -s .travis.yml .yamllint.yml
  • yamllint -c .yamllint.yml -s $(find . -type f -name “Chart.yaml”)
  • yamllint -c .yamllint.yml -s $(find . -type f -name “values.yaml”)

The script section should look like the below config

 # Check charts format
 - >
    for dir in `ls ${REPO_DIR}/${CHART_FOLDER}`; do
     helm lint ${REPO_DIR}/${CHART_FOLDER}/$dir
     if [ $? != 0 ]; then
      travis_terminate 1
 # Check YAML styling
 - yamllint -c .yamllint.yml -s .travis.yml .yamllint.yml
 - yamllint -c .yamllint.yml -s $(find . -type f -name "Chart.yaml")
 - yamllint -c .yamllint.yml -s $(find . -type f -name "values.yaml")

Here comes the interesting part where we are going to build and package the chart.

Lifecycle 4:

It’s better to build and push when we merge the chart in the master branch. So we run the below command when we merge the chart in the master branch

We need a temporary directory where we will build and package the chart

  • BUILD_DIR=$(mktemp -d)

Run a loop to all the charts to build, package, and push it to the registry. The below commands will run on each chart

  • helm dep update ${REPO_DIR}/${CHART_FOLDER}/$dir

Package the chart with the below command

  • helm package ${REPO_DIR}/${CHART_FOLDER}/$dir

Then push the chart to registry

  • helm push — username ${HARBOR_USERNAME} — password ${HARBOR_PASSWORD} ${REPO_DIR}/${CHART_FOLDER}/$dir ${HARBOR_CHART_URL}/maya

Below is the what the config will look like

# Temporary dir for storing new packaged charts and index files
     BUILD_DIR=$(mktemp -d)
     # Push temporary directory to the stack
     pushd $BUILD_DIR
     # Iterate over all charts are package them push it to Harbor
     for dir in `ls ${REPO_DIR}/${CHART_FOLDER}`; do
      helm dep update ${REPO_DIR}/${CHART_FOLDER}/$dir
      helm package ${REPO_DIR}/${CHART_FOLDER}/$dir
      helm push --username ${HARBOR_USERNAME} --password ${HARBOR_PASSWORD}  ${REPO_DIR}/${CHART_FOLDER}/$dir ${HARBOR_CHART_URL}/maya
      if [ $? != 0 ]; then
       travis_terminate 1
# Pop temporary directory from the stack

Wow! We have successfully completed all the steps. Now, our setup is ready to build and push the helm chart to the registry.

Helm charts

Here is the full Travis file

Here is .yamllint.yml file which contains lint rule for charts.yaml values.yaml and .travis.yaml


Here we packaged the helm chart and pushed it to the helm registry.

About me

You can follow me at the below profiles and can ask any questions related to Angular, JavaScript, Travis, Kubernetes, etc.


Murat Karslioglu
VP @OpenEBS & @MayaData_Inc. Murat Karslioglu is a serial entrepreneur, technologist, and startup advisor with over 15 years of experience in storage, distributed systems, and enterprise hardware development. Prior to joining MayaData, Murat worked at Hewlett Packard Enterprise / 3PAR Storage in various advanced development projects including storage file stack performance optimization and the storage management stack for HPE’s Hyper-converged solution. Before joining HPE, Murat led virtualization and OpenStack integration projects within the Nexenta CTO Office. Murat holds a Bachelor’s Degree in Industrial Engineering from the Sakarya University, Turkey, as well as a number of IT certifications. When he is not in his lab, he loves to travel, advise startups, and spend time with his family. Lives to innovate! Opinions my own!
Jeffry Molanus
Jeffry prior to being CTO at MayaData has worked at several other startups in the storage industry. He worked on several scale-out object storage products as well as traditional NAS and SAN storage solutions where he held technical leadership roles. At MayaData, his primary focus is to make sure the product is flexible and scalable. At the same time, robust enough to be integrated seamlessly into modern-day infrastructure where he believes, containers will have a dominant role. Jeffry holds a master's degree in electrical engineering with a focus on distributed control engineering from the University of Twente in the Netherlands. When he is not working with code, he practices martial arts.
Abhishek Raj
Abhishek is a Customer Success Engineer at Mayadata. He is currently working with Kubernetes and Docker.