Helm Chart

Helm is a popular package manager for deploying applications on Kubernetes. But, those packages can be outdated quickly. In this guide we explore how we can automatically update Helm charts based on third-party dependencies.

Requirement

To use this guide, we need the following elements:

  1. Updatecli

  2. A Helm chart to update

  3. A GitHub Personal Access Token

Updatecli

Updatecli is a declarative dependency management tool. The application is available as a command line compatible with Linux/macOS/Windows. Updatecli is designed to work the same way, both from a local machine and a CI environment.

It can easily be installed using Homebrew by running the two following commands:

-> brew tap updatecli/updatecli
-> brew install updatecli

Additional installation instructions are available at www.updatecli.io/docs/prologue/installation.

IDE

The best way to write Updatecli manifest(s) is by using an IDE compatible with jsonschema hosted on schemastore.org, such as Vscode, Intellij, or Neovim. The full list of compatible IDE is available on www.schemastore.org.

For the IDE to load the correct Updatecli jsonschema, Updatecli manifest must have both a parent directory named "updatecli.d" and one of the file extension ".yaml", or ".yml". This provides auto-completion and validation out of the box.

For example, from VScode, typing [ctrl][space] should display a box with various suggestions

Helm chart to update

Within this example, we’ll use a Helm chart from the Jenkins infrastructure project located on github.com/jenkins-infra/helm-charts. We want to check that the Helm chart is always using the latest chart application which, in this case, is the jenkins-wiki-exporter.

GitHub Personal Access Token

As we’re going to interact with GitHub repository and GitHub packages, we need a personal access token. More information on the GitHub documentation creating-a-personal-access-token

Pipeline

Manifest

Updatecli expects one or more pipeline manifests to know what to do. We use the command updatecli pipeline diff --config updatecli.yaml to load the manifest. The diff allows us to run updatecli in dry-mode, identifying what updatecli would change. Then we execute updatecli pipeline apply --config updatecli.yaml to apply our updatecli pipeline.

As you’ll see in our updatecli manifest, we define:

  1. One "source" of kind "githubrelease" which describes where to retrieve the latest version of our application, jenkins-wiki-exporter, published on GitHub Release.

  2. Two "conditions" which need to be satisfied before updating our Helm chart. The first one, "DockerImagePublished" of kind "dockerimage", ensures that a Docker image "jenkinsciinfra/jenkins-wiki-exporter" exists on DockerHub where the tag is the same as the source output, the latest jenkins-wiki-exporter version. The second one, "DockerContainerUsed" of kind "yaml", ensures that our Helm chart uses the right container name, "jenkinsciinfra/jenkins-wiki-exporter".

  3. A "target" of kind "helmchart", with a chart name "charts/jenkins-wiki-exporter" and a file "values.yaml" where the key "image.tag" is set to the latest jenkins-wiki-exporter version. If it’s not the case then bump the patch version of the chart, as requested by versionincrement: "patch".

  4. An "scms" entry of kind "github", that describes which GitHub repository stores the Helm chart "code".

  5. An "actions" entry of kind "github/pullrequest", that describes pull request parameters such as the labels assigned to the pull request created by updatecli, and the auto-merge strategy.

updatecli.yaml
name: "Bump `jenkins-wiki-exporter` docker image and helm chart versions"

sources:
  jenkins-wiki-exporter:
    kind: "githubrelease"
    name: "Get jenkins-infra/jenkins-wiki-exporter latest version"
    spec:
      owner: "jenkins-infra"
      repository: "jenkins-wiki-exporter"
      token: '{{ requiredEnv "GITHUB_TOKEN" }}'
      username: '{{ requiredEnv "GITHUB_ACTOR" }}'
      # Added to take care of "v" prefix in version until the chart is updated to use the semver versioning (which doesn't have the "v" prefix)
      versionfilter:
        kind: "latest"

conditions:
  DockerImagePublished:
    name: "Test jenkinsciinfra/jenkins-wiki-exporter:<latest_version> docker image tag"
    kind: "dockerimage"
    sourceid: "jenkins-wiki-exporter"
    spec:
      image: "jenkinsciinfra/jenkins-wiki-exporter"
      architecture: "amd64"
      # tag retrieved from source output "jenkinswikiexporter"
  DockerContainerUsed:
    name: "Test jenkinsciinfra/jenkins-wiki-exporter:<latest_version> docker image tag"
    kind: "yaml"
    disablesourceinput: true
    scmid: "helm-charts"
    spec:
      file: "charts/jenkins-wiki-exporter/values.yaml"
      value: "jenkinsciinfra/jenkins-wiki-exporter"
      key: "image.repository"
targets:
  jenkins-wiki-exporter:
    name: "Update jenkins-wiki-exporter helm chart"
    kind: "helmchart"
    spec:
      name: "charts/jenkins-wiki-exporter"
      file: "values.yaml"
      key: "image.tag"
      versionincrement: "patch"
    scmid: "helm-charts"
    sourceid: "jenkins-wiki-exporter"

scms:
  helm-charts:
    kind: "github"
    spec:
      branch: "main"
      user: "updatecli-robot"
      email: "bot@updatecli.io"
      owner: "jenkins-infra"
      repository: "helm-charts"
      token: '{{ requiredEnv "GITHUB_TOKEN" }}'
      username: '{{ requiredEnv "GITHUB_ACTOR" }}'

actions:
  default:
    kind: "github/pullrequest"
    scmid: "helm-charts"
    spec:
      merge:
        strategy: auto
      labels:
        - "dependencies"
        - "jenkins-wiki-exporter"

Now we run our updatecli pipeline using the following commands:

export UPDATECLI_GITHUB_TOKEN=xxx
export UPDATECLI_GITHUB_ACTOR=yyy
updatecli pipeline diff --config updatecli.yaml
Warning
Using environment variables to store credentials is convenient for running updatecli from a CI environment. Another option is to use sops but in either case, you should not leave your credentials unprotected.

Spoiler Alert: Command output

+++++++++++
+ PREPARE +
+++++++++++

Loading Pipeline "assets/code_example/doc/guides/helm-chart/updatecli.yaml"
Repository retrieved: 1


++++++++++++
+ PIPELINE +
++++++++++++



#####################################################################
# BUMP `JENKINS-WIKI-EXPORTER` DOCKER IMAGE AND HELM CHART VERSIONS #
#####################################################################


SOURCES
=======

jenkins-wiki-exporter
---------------------
Searching for version matching pattern "latest"
✔ Github Release version "v1.12.1" found matching pattern "latest"


CHANGELOG:
----------

Release published on the 2021-10-02 18:36:27 +0000 UTC at the url https://github.com/jenkins-infra/jenkins-wiki-exporter/releases/tag/v1.12.1

<!-- Optional: add a release summary here -->
* Dont allow non pull requests in the project from breaking the report (#303) @halkeye

## 📦 Dependency updates

* Bump node from 16.7.0 to 16.8.0 (#288) @dependabot
* Bump jest from 27.0.6 to 27.1.0 (#287) @dependabot



CONDITIONS:
===========

DockerContainerUsed
-------------------
✔ Key "image.repository", in YAML file "/tmp/updatecli/jenkins-infra/helm-charts/charts/jenkins-wiki-exporter/values.yaml", is correctly set to "jenkinsciinfra/jenkins-wiki-exporter"

DockerImagePublished
--------------------
^[[B✔ The Docker image registry-1.docker.io/jenkinsciinfra/jenkins-wiki-exporter:v1.12.1 exists and is available.


TARGETS
========

jenkins-wiki-exporter
---------------------

**Dry Run enabled**

✔ Key 'image.tag', from file '/tmp/updatecli/jenkins-infra/helm-charts/charts/jenkins-wiki-exporter/values.yaml', already set to v1.12.1, nothing else need to be done


PULL REQUESTS
=============


=============================

REPORTS:


✔ UPDATECLI.YAML:
	Sources:
		✔ [jenkins-wiki-exporter] Get jenkins-infra/jenkins-wiki-exporter latest version (kind: githubRelease)
	Condition:
		✔ [DockerContainerUsed] Test jenkinsciinfra/jenkins-wiki-exporter:<latest_version> docker image tag (kind: yaml)
		✔ [DockerImagePublished] Test jenkinsciinfra/jenkins-wiki-exporter:<latest_version> docker image tag (kind: dockerimage)
	Target:
		✔ [jenkins-wiki-exporter] Update jenkins-wiki-exporter helm chart (kind: helmchart)



Run Summary
===========
Pipeline(s) run:
  * Changed:	0
  * Failed:	0
  * Skipped:	0
  * Succeeded:	1
  * Total:	1

Go Further

Updatecli is used in more scenarios and with many more to come. Please reach out if you have questions. Meanwhile, here are additional resources that you can use to go further.

Resource

To extend this pipeline, you can find more customization on the updatecli documentation website.

In this pipeline we used the following resources:

Additional Workflows

Updatecli shines and saves us time in many other situations such as:

  • Docker Compose - keeping a docker-compose.yaml on the latest image tag or digest.

  • Dockerfile - how the Jenkins project keeps its Dockerfiles on the latest JDK.

  • npm - tracking an npm dependency and refreshing the lock file.

Contributing

As a community-oriented project, all contributions are greatly appreciated!

Here is a non-exhaustive list of possible contributions:

  • ⭐️ this updatecli/updatecli repository.

  • Propose a new feature request.

  • Highlight an existing feature request with :thumbsup:.

  • Contribute to any repository in the updatecli organization

  • Share the love

More information is available at CONTRIBUTING