Helm
Provides helpers for deploying Helm charts from a Git repository, a Helm repository, or an OCI registry.
Usage
include:
- project: hosstio/gitlab-pipelines
file: helpers/helm.yamlVariables
Registry
| Variable | Default | Description |
|---|---|---|
HELM_REGISTRY | $CI_REGISTRY | Helm OCI registry host |
HELM_REGISTRY_USER | $CI_REGISTRY_USER | Registry username |
HELM_REGISTRY_PASSWORD | $CI_JOB_TOKEN | Registry password |
Chart
| Variable | Default | Description |
|---|---|---|
HELM_CHART | ./helm-charts/charts/standard | Local path to the chart; set automatically for OCI repositories |
HELM_CHART_VERSION | "" | Version to pin: semver for OCI/helm repo, branch/tag for git; omit for latest/default branch |
HELM_RELEASE | $CI_PROJECT_NAME | Helm release name |
HELM_NAMESPACE | $KUBERNETES_NAMESPACE | Kubernetes namespace |
Repository
| Variable | Default | Description |
|---|---|---|
HELM_REPOSITORY | gitlab.com/hosstio/helm-charts.git | Chart source, auto-detected by prefix/suffix (see table below) |
HELM_REPOSITORY_NAME | "" | Local alias used with helm repo add; required when using a plain Helm repository URL |
HELM_REPOSITORY_USER | gitlab-ci-token | Repository auth username (git clone) |
HELM_REPOSITORY_PASSWORD | $CI_JOB_TOKEN | Repository auth password |
Repository auto-detection
HELM_REPOSITORY value | Behaviour |
|---|---|
| empty | Skipped; use when referencing a local chart or passing an OCI reference directly in HELM_CHART |
oci://... | helm pull --untar; HELM_CHART is set automatically to the pulled chart directory |
*.git or git@... | git clone --depth 1; use HELM_CHART to point into the cloned tree |
| anything else | helm repo add $HELM_REPOSITORY_NAME $HELM_REPOSITORY + helm repo update; each helm command that takes the chart gets --version $HELM_CHART_VERSION through HELM_CHART_ARGS |
Command
| Variable | Default | Description |
|---|---|---|
HELM_ACTION | upgrade | Helm subcommand |
HELM_ARGS | --install --wait --server-side=true --force-conflicts | Core helm arguments; see Manual changes |
HELM_ROLLBACK_ARGS | --server-side=true --force-conflicts | Extra arguments for helm rollback, after a failed deploy and in the rollback:<environment> jobs |
HELM_EXTRA_ARGS | "" | Additional arguments |
HELM_ARGS_SECRET | "" | Secret arguments (masked in logs) |
HELM_EXTRA_ARGS_SECRET | "" | Additional secret arguments (masked in logs) |
HELM_VALUES | "" | Space or comma-separated values files, converted to --values flags automatically |
HELM_FILES | "" | Space or comma-separated key=filepath pairs, converted to --set-file flags |
HELM_RELEASE_ARGS | --namespace $HELM_NAMESPACE | Namespace and release-specific arguments passed to every helm command; overridden in preview to add --set fullnameOverride=$HELM_RELEASE so branch instances are named after the release rather than the chart |
HELM_DIFF_OUTPUT | dyff | Diff output format for the Slack summary: dyff shows structured output with full YAML paths, diff shows a unified context diff |
HELM_DIFF_CONTEXT | 8 | Lines of context around each change in the Slack summary; relevant when HELM_DIFF_OUTPUT is diff, ignored by dyff |
HELM_DIFF_ARGS | --allow-unreleased --suppress-secrets --three-way-merge | Base arguments for the full diff artifact: --allow-unreleased permits diff before the first deploy, --suppress-secrets hides secret values, --three-way-merge diffs against the live objects |
HELM_DIFF_SUMMARY_ARGS | $HELM_DIFF_ARGS --output $HELM_DIFF_OUTPUT --context $HELM_DIFF_CONTEXT | Arguments for the Slack summary diff; extends HELM_DIFF_ARGS with output format and context limit |
Manual changes
Deploys apply server-side with --force-conflicts. When another field manager last wrote a field, such as a manual kubectl apply or a controller, the deploy sets it back to the chart's value instead of failing. The diff runs with --three-way-merge against the live objects, so the job log shows those manual changes before the deploy reverts them. Rollbacks force conflicts the same way (HELM_ROLLBACK_ARGS), so a field the failed deploy took over doesn't block its rollback.
To make such a conflict fail the deploy instead, set HELM_ARGS without --force-conflicts on .deploy, and HELM_ROLLBACK_ARGS to --server-side=true. .helm:install sets HELM_ARGS at job level, so a global variables: override has no effect.
Helpers
Repository setup (.helm_repository)
Fetches the chart from HELM_REPOSITORY. Behaviour depends on the repository type; see the auto-detection table above. Referenced by .helm before_script.
Values args (.helm_values_args)
Converts HELM_VALUES and HELM_FILES into HELM_VALUES_ARGS and HELM_FILES_ARGS shell variables (--values file1 --values file2 ...). Referenced by .helm before_script.
Current values (.helm_values_current)
Writes the currently deployed user-supplied values to helm-values-current.yaml via helm get values. Referenced by .helm_diff script.
New values (.helm_values_new)
Runs helm upgrade --dry-run --debug and extracts the USER-SUPPLIED VALUES section into helm-values.txt. Referenced by .helm_diff script.
Chart version (.helm_chart_version)
Resolves the current deployed chart version from helm list and the incoming chart version from Chart.yaml. For git-cloned charts, appends the branch and commit SHA (e.g. standard-1.2.3 main (a1b2c3d4)). Prepends a chart: line to both helm-values-current.yaml and helm-values.txt so chart upgrades appear in the diff. Referenced by .helm_diff script.
Base (.helm)
Sets up the chart source and resolves values args before any deploy script runs. Calls .helm_repository and .helm_values_args. After setup, all HELM_* variables are printed to the job log.
Deploy (.helm_install)
Extends .helm. Runs helm $HELM_ACTION $HELM_RELEASE $HELM_CHART with all variable flags composed in order. Output is saved to helm-install.txt and exposed as a Helm Install artifact.
Examples
Git-hosted chart (default)
deploy:
extends: .helm_install
variables:
HELM_VALUES: "kubernetes/helm/values.yaml kubernetes/helm/production.yaml"
HELM_RELEASE: my-appPublic Helm repository
deploy:
extends: .helm_install
variables:
HELM_REPOSITORY: https://charts.bitnami.com/bitnami
HELM_REPOSITORY_NAME: bitnami
HELM_CHART: bitnami/postgresql
HELM_RELEASE: postgresqlOCI chart referenced directly (no pull)
deploy:
extends: .helm_install
variables:
HELM_REPOSITORY: ""
HELM_CHART: oci://ghcr.io/nginx/charts/nginx-ingress
HELM_NAMESPACE_ARGS: "--namespace $HELM_NAMESPACE"
HELM_RELEASE: nginx-ingressOCI chart pulled first (auto-sets HELM_CHART)
deploy:
extends: .helm_install
variables:
HELM_REPOSITORY: oci://ghcr.io/nginx/charts/nginx-ingress
HELM_CHART_VERSION: "1.3.4"
HELM_NAMESPACE_ARGS: "--namespace $HELM_NAMESPACE"
HELM_RELEASE: nginx-ingressDiff (.helm_diff)
Extends .helm_install. Runs in the plan stage with needs: [] so it executes immediately without waiting for earlier stages. Sets environment: action: prepare so the job does not register as a deployment. Clears after_script so Slack notifications are not sent.
Produces the following artifacts (exposed as Helm Diff):
| File | Content |
|---|---|
helm-values-current.yaml | User-supplied values of the currently deployed release |
helm-values.txt | User-supplied values of the incoming release |
helm-values-diff.txt | Unified diff between current and incoming values |
helm-values-dyff.txt | Structured (dyff) diff between current and incoming values |
helm-values-summary.txt | Human-readable summary derived from helm-values-dyff.txt; see Values summary format |
helm-kubernetes-diff.txt | Unified diff of rendered Kubernetes manifests |
helm-kubernetes-dyff.txt | Structured (dyff) diff of rendered Kubernetes manifests |
kubernetes-manifests.txt | Full rendered manifests for the incoming release |
helm-plan.json | Resource change counts ({"create": N, "update": N, "delete": N}), rendered as a Terraform widget in the MR; see Terraform plan report |
diff:
extends:
- .deploy_staging
- .helm_diffJob log sections
| Section | Default | Description |
|---|---|---|
| Helm Repository | collapsed | Chart source setup: clones, pulls, or registers the repository |
| Helm Environment | collapsed | All HELM_* variables resolved for this run |
| Helm Values — User-supplied | collapsed | Group wrapper for user-supplied value sections |
| Helm Values Files | collapsed | Source values files passed via HELM_VALUES |
| Helm Values (active) | collapsed | Currently deployed user-supplied values (helm get values) |
| Helm Values (new) | collapsed | Proposed user-supplied values (from dry-run) |
| Helm Values Diff | open | Unified diff of user-supplied values: active → new |
| Helm Values Dyff | collapsed | Structured dyff of user-supplied values: active → new |
| Helm Values Summary | open | Human-readable change summary (see Values summary format) |
| Helm Values — Computed | collapsed | Group wrapper for computed (chart defaults + user) value sections |
| Helm Values (active, all) | collapsed | Currently deployed computed values (helm get values --all) |
| Helm Values (new, all) | collapsed | Proposed computed values (from dry-run) |
| Helm Values Diff (all) | collapsed | Unified diff of computed values: active → new |
| Helm Values Dyff (all) | collapsed | Structured dyff of computed values: active → new |
| Helm Values Summary (all) | collapsed | Human-readable change summary for computed values |
| Helm Kubernetes Manifests | collapsed | Full rendered Kubernetes manifests for the incoming release |
| Helm Kubernetes Diff | open | Unified diff of rendered Kubernetes manifests |
| Helm Kubernetes Dyff | collapsed | Structured dyff of rendered Kubernetes manifests |
| Helm Plan | collapsed | Resource change counts, also rendered as a Terraform widget on the MR |
Terraform plan report
helm-plan.json contains resource change counts in the format GitLab's artifacts: reports: terraform parser expects:
{"create": 2, "update": 1, "delete": 0}GitLab renders this as a Terraform widget on the merge request showing how many Kubernetes resources will be added, changed, or destroyed, without needing to open the job.
The counts are computed by comparing helm-kubernetes-current.yaml (current live manifests via helm get manifest) against helm-kubernetes-new.yaml (rendered incoming manifests via helm template), keyed by Kind/name, the Kubernetes-native convention used by kubectl and helm (e.g. Deployment/fileupload, ConfigMap/fileupload-variables):
| Condition | Counted as |
|---|---|
| Present in new only | create |
| Present in current only | delete |
| Present in both, content differs | update |
| Present in both, content identical | not counted |
Secrets are never included: they are stripped when helm-kubernetes-current.yaml and helm-kubernetes-new.yaml are generated.
The following labels are stripped from both sides before comparing, so a version bump alone does not count as an update:
app.kubernetes.io/versionhelm.sh/chart
Values summary format
helm-values-summary.txt is a compact, human-readable representation of what changed in the Helm values. It is derived from helm-values-dyff.txt (a semantic YAML diff of the values files) rather than helm-values-diff.txt (a raw unified diff), because dyff understands YAML structure and can group related changes under their parent keys.
Rules
| Change type | Format |
|---|---|
| Scalar changed | key: old -> new |
| Scalar added | key: value (added) |
| Scalar removed | key: value (removed) |
| List item added | - value (added) |
| List item removed | - value (removed) |
| Parent key | key: (printed once, only when a child is emitted) |
| Chart version | chart: old -> new (first line, only when chart changes) |
YAML hierarchy is preserved with 2-space indentation per level. Parent keys are printed only when at least one child change is emitted beneath them.
Example
chart: standard-1.2.3 main (abc1234) -> standard-1.2.3 main (def5678)
image:
tag: b19b1cd9 -> 394fc1e1
repository: old.registry.com/app -> new.registry.com/app
replicaCount: 2 -> 3
resources:
limits:
memory: 256Mi -> 512Mi
autoscaling:
enabled: true -> false
name: autoscaling (removed)
envFrom:
- configMapRef: old-config (removed)
newFeature:
enabled: true (added)