Deploy/Upgrade from Helm Charts in Git Repo
This guide shows a practical CI/CD flow where your Helm charts live under a charts/ directory in your Git repo.
We'll use Pipeline to:
- Clone the repository with the
git-clone Task
- Deploy/upgrade a target chart with Helm (
helm upgrade --install)
You'll Build a reusable Pipeline named helm-deploy-from-git-repo that:
- Pulls your repo
- Runs
helm dependency build (so subcharts are fetched)
- Runs
helm upgrade --install for a chart at charts/<name> (or any subpath you choose)
- Supports
--wait, --timeout, --atomic, extra args, multiple values files, and --set kv pairs
TOC
Prerequisites
- A Kubernetes cluster (you can use minikube for local testing).
- Tekton Pipelines installed on your cluster.
- A Helm 3.8+ container image (Helm v3 with OCI support).
- A Git repository that contains a valid Helm chart (directory with
Chart.yaml, templates/, values.yaml).
- Git access to the repository:
- Public repo: nothing special.
- Private repo: create a Git credential Secret (SSH or basic-auth).
- Cluster access for Helm (choose one):
- Mount a Kubeconfig Secret,
- Run the Task under a ServiceAccount with sufficient RBAC.
Step-by-Step Instructions
Step 1: Create Cluster Access Credential
You need a cluster access credential for Helm.
You can refer to the Prepare Cluster Access Credential.
Step 2: Prepare helm image
You need a Helm 3.8+ container image (Helm v3 with OCI support) to run the helm command.
You can refer to the Discover Tool Image.
When searching by label, specify the image as helm, for example: -l operator.tekton.dev/tool-image=helm.
Step 3: Define the Pipeline
This Pipeline uses git-clone to fetch your repo, then calls helm to install or upgrade your chart.
You can use --wait to blocks until Kubernetes reports the release's resources are ready (or until the operation times out).
Pair it with --timeout to control how long Helm will wait.
It's common to combine with --atomic, which rolls back automatically if the wait fails or times out—so you don't leave a half-upgraded release.
Please replace <helm-image> with your Helm image.
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: helm-deploy-from-git-repo
spec:
description: Clone repo, package Helm chart, and push to an OCI registry.
params:
- name: repo_url
type: string
description: Git URL of your repository
- name: revision
type: string
description: Git revision (branch, tag, or SHA)
default: main
- name: chart_dir
type: string
description: Path to the Helm chart in the repo
default: "."
- name: release_name
type: string
description: Helm release name
- name: namespace
type: string
description: Target namespace
default: default
- name: extra_args
type: string
description: Extra helm args (e.g., "--atomic --timeout 5m --set key=val -f values.yaml")
default: ""
workspaces:
- name: source
- name: basic-auth
optional: true
- name: kubeconfig
optional: true
tasks:
- name: git-clone
taskRef:
resolver: hub
params:
- name: catalog
value: catalog
- name: kind
value: task
- name: name
value: git-clone
- name: version
value: "0.9"
workspaces:
- name: output
workspace: source
- name: basic-auth
workspace: basic-auth
params:
- name: url
value: $(params.repo_url)
- name: revision
value: $(params.revision)
- name: helm
runAfter:
- "git-clone"
taskRef:
resolver: hub
params:
- name: catalog
value: catalog
- name: kind
value: task
- name: name
value: run-script
- name: version
value: "0.1"
workspaces:
- name: source
workspace: source
- name: secret
workspace: kubeconfig
params:
- name: image
## Replace with your Helm image
value: <helm-image>
- name: script
value: |
set -e
if [ "$(workspaces.secret.bound)" = "true" ]; then
echo "Using kubeconfig in $(workspaces.secret.path)"
export KUBECONFIG=$(workspaces.secret.path)/kubeconfig
fi
echo "Build chart dependencies (if any)…"
helm dependency build "$(params.chart_dir)"
echo "Upgrading/Installing release..."
echo " Release: $(params.release_name)"
echo " Namespace: $(params.namespace)"
echo " Chart: $(params.chart_dir)"
# Direct install from OCI (no need to helm pull first)
helm upgrade --install "$(params.release_name)" "$(params.chart_dir)" \
--namespace "$(params.namespace)" --create-namespace \
$(params.extra_args)
echo "Done."
Step 4: Run It with a PipelineRun
- Cluster access for Helm (choose one):
- Mount a Kubeconfig Secret,
- Run the Task under a ServiceAccount with sufficient RBAC.
Please choose one of cluster access credentials.
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: helm-deploy-from-git-repo-
spec:
workspaces:
- name: source
volumeClaimTemplate:
spec:
## Specify StorageClassName (as needed)
# storageClassName: <storage-class-name>
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- name: basic-auth
secret:
secretName: basic-auth
## If you choose to use the kubeconfig Secret
# - name: kubeconfig
# secret:
# secretName: <kubeconfig-secret-name>
params:
- name: repo_url
value: https://github.com/your-org/your-repo.git
- name: revision
value: main
- name: chart_dir
value: .
- name: release_name
value: myapp
- name: namespace
value: my-namespace
pipelineRef:
name: helm-deploy-from-git-repo
## If you choose to use the ServiceAccount
# taskRunTemplate:
# serviceAccountName: <service-account-name>
Troubleshooting
helm: command not found: Ensure your image actually contains the Helm binary.
failed to create resource: (…RBAC…) forbidden: The kubeconfig/ServiceAccount lacks permissions. Grant the necessary roles to create/update the resources the chart manages.
Next Steps