Pass dynamic parameters to Helm in GitLab-CI

Stefan Steinert
3 min readJan 8, 2021

For a project I got the need to dynamically change the environment parameters of the deployment without always updating the projects code. This collides a bit with my opinion that every change should be reflected in your VCS, but comes in very handy when you have to quickly introduce new values in debugging situations.

In general it is a very small script snippet, but due to the restricted environment in which the CI pipeline within GitLab is executed we can not use the full capabilities of bash/sh.

The general process is to iterate through the environment variables injected by GitLab and add them as --set Helm parameters if they match a certain pattern.

The short version of the script snippet would be the following (which will not work in .gitlab-ci.yml)

for VARNAME in ${!ENV_@}; do
ENVVARS="${ENVVARS} --set ${VARNAME/ENV_/env.}=${!VARNAME}";
done

So let’s rewrite this to work directly within the script section of a .gitlab-ci.yml job.

I assume that you are familiar with the basics of Helm. I will use a basic Helm project as it is created by using the helm create command.

As first step we will update the values.yaml file to have an empty “env” object by adding the following line:

env: {}

Afterwards we update the templates/deployment.yaml file to include our newly added environment variables

containers:
- name: {{ .Chart.Name }}
env:
{{- range $key, $value := .Values.env }}
- name: "{{ $key }}"
value: "{{ $value }}"
{{- end }}

The Helm part is done by that.

We can now create the deployment in the .gitlab-ci.yml file. As mentioned earlier we have to find some workarounds since we don’t have a full bash/sh available.

So we will iterate the output of the env command and parse the values from there into the parameters we require for Helm.

Since we want to pass environment variables we choose “ENV_” as prefix for them, which makes them easy to identify and matches the name we used in the Helm values. The only additional thing we have to perform is to replace the “ENV_” with “env.”, to have them recognized by Helm. Due to naming restrictions we can not directly create the variables as “env.VAR_NAME”.

for VARNAME in $(env); do
if [[ $( echo $VARNAME | egrep '^ENV_') ]]; then
echo -e $VARNAME;
NAME=$(echo "$VARNAME" | cut -d"=" -f1 | sed "s/ENV_/env./");
VAR=$(echo "$VARNAME" | cut -d"=" -f2-);
ENVVARS="${ENVVARS} --set $NAME=$VAR";
fi
done

We add this as before_script and utilize the output within the main script section in which we perform the actual deployment.

before_script:
- for VARNAME in $(env); do
if [[ $( echo $VARNAME | egrep '^ENV_') ]]; then
echo -e $VARNAME;
NAME=$(echo "$VARNAME" | cut -d"=" -f1 | sed "s/ENV_/env./");
VAR=$(echo "$VARNAME" | cut -d"=" -f2-);
ENVVARS="${ENVVARS} --set $NAME=$VAR";
fi
done
script:
- |
helm upgrade --install nginx ./deployment/helm \
$ENVVARS

We can now add variables in the GitLab UI with the prefix “ENV_” and they will be recognized on next deployment. You will not have to update your .gitlab-ci.yml to introduce the variables.

With this you are able to quickly add environment variables to your deployments in testing and debugging situations without having to update any file in your project or the need of running the full pipeline.

Just change/add the environment variable in the GitLab UI and execute your deployment step once again.

Full Code Example

--

--

Stefan Steinert

System Operator and DevOPs Architect since childhood