Helm ReleaseTrigger

Helm ReleaseTrigger

Certified

Trigger a flow when a Helm release changes state

Polls the Helm release records on a cluster and starts a flow when a release reaches a new revision or a new status, whoever made the change: a Kestra task, a CI pipeline, or someone running helm by hand.

Reads Helm's release Secrets (owner=helm) through the Kubernetes API, so no Helm container runs on each poll. Only the latest revision of each release is considered, so a revision that failed long ago and has since been superseded does not fire again.

The first evaluation treats every release already on the cluster as new; set on: UPDATE to react only to changes made after the trigger starts.

Requires list and get permissions on secrets in the watched namespaces, or cluster-wide with allNamespaces. Kubernetes RBAC cannot narrow that permission to Helm's Secrets, so prefer a namespace-scoped Role. Without get, releases still fire but without chart details. Only releases stored with Helm's default secret storage driver are seen.

yaml
type: io.kestra.plugin.helm.ReleaseTrigger

Alert on any release that fails in a namespace

yaml
id: helm_failed_release_alert
namespace: company.team

tasks:
  - id: each_release
    type: io.kestra.plugin.core.flow.ForEach
    values: "{{ trigger.releases }}"
    tasks:
      - id: slack
        type: io.kestra.plugin.slack.SlackIncomingWebhook
        url: "{{ secret('SLACK_WEBHOOK') }}"
        payload: |
          {
            "text": "Helm release {{ fromJson(taskrun.value).releaseName }} failed at revision {{ fromJson(taskrun.value).revision }}: {{ fromJson(taskrun.value).description }}"
          }

triggers:
  - id: failed_release
    type: io.kestra.plugin.helm.ReleaseTrigger
    namespace: web
    statuses:
      - FAILED
    cluster: prod-eu
    kubeconfig: "{{ secret('PROD_EU_KUBECONFIG') }}"

Roll back a release stuck in pending-upgrade for 15 minutes

yaml
id: helm_unstick_release
namespace: company.team

tasks:
  - id: rollback
    type: io.kestra.plugin.helm.Rollback
    releaseName: "{{ trigger.releases[0].releaseName }}"
    namespace: "{{ trigger.releases[0].namespace }}"
    kubeconfig: "{{ secret('PROD_EU_KUBECONFIG') }}"

triggers:
  - id: stuck
    type: io.kestra.plugin.helm.ReleaseTrigger
    namespace: web
    releaseName: nginx
    statuses:
      - PENDING_UPGRADE
    stuckFor: PT15M
    kubeconfig: "{{ secret('PROD_EU_KUBECONFIG') }}"

Smoke-test every new revision that reaches deployed

yaml
id: helm_post_deploy_smoke_test
namespace: company.team

tasks:
  - id: each_release
    type: io.kestra.plugin.core.flow.ForEach
    values: "{{ trigger.releases }}"
    tasks:
      - id: healthz
        type: io.kestra.plugin.core.http.Request
        uri: "https://{{ fromJson(taskrun.value).releaseName }}.example.com/healthz"

triggers:
  - id: deployed
    type: io.kestra.plugin.helm.ReleaseTrigger
    allNamespaces: true
    releaseNamePattern: "^api-.*"
    statuses:
      - DEPLOYED
    on: UPDATE
    connection:
      masterUrl: https://prod-eu.k8s.example.com
      caCertData: "{{ secret('PROD_EU_CA') }}"
      oauthToken: "{{ secret('PROD_EU_TOKEN') }}"
Properties
Defaultfalse

Watch every namespace

Watches releases in all namespaces. Needs a ClusterRole that can list and get Secrets cluster-wide.

Defaultfalse

Specifies whether a trigger is allowed to start a new execution even if a previous run is still in progress.

Cluster name

Reported as cluster on each release in the trigger output, resolved the same way as on the tasks so the two can be joined. Defaults to the host of the Kubernetes API server when connection is used, and is null otherwise. Set it explicitly to match the name your team uses, e.g. prod-eu.

Kubernetes connection

Cluster credentials, using the same model as the Kubernetes plugin. Mutually exclusive with kubeconfig. If neither is set, the trigger uses the kubeconfig or service account available to the Kestra worker.

Definitions
apiVersionstring
Defaultv1

API version

API group version used by the client. Default v1.

caCertDatastring

CA certificate data

Base64-encoded PEM CA bundle. Whitespace is stripped automatically.

caCertFilestring

CA certificate file

Path to a PEM CA bundle.

clientCertDatastring

Client certificate data

Base64-encoded client cert. Whitespace is stripped automatically.

clientCertFilestring

Client certificate file

clientKeyAlgostring
DefaultRSA

Client key algorithm

Algorithm for the client key. Default RSA.

clientKeyDatastring

Client key data

Base64-encoded client key. Whitespace is stripped automatically.

clientKeyFilestring

Client key file

clientKeyPassphrasestring

Client key passphrase

disableHostnameVerificationbooleanstring

Disable hostname verification

Disables TLS hostname checks. Avoid in production clusters.

enableHttp2booleanstring

Enable HTTP/2

Off by default (HTTP/1.1, the prior behavior). Enable to use HTTP/2, which keeps long-lived watch/log streams alive better through proxies like GKE konnectivity.

keyStoreFilestring

Keystore file

keyStorePassphrasestring

Keystore passphrase

masterUrlstring
Defaulthttps://kubernetes.default.svc

Kubernetes API URL

API server endpoint. Default https://kubernetes.default.svc.

maxConcurrentRequestsintegerstring

Max concurrent HTTP requests

Caps total concurrent HTTP requests issued by this client. Lower this when running many concurrent tasks against a rate-limited API server (e.g. GKE). Fabric8 default: 64.

maxConcurrentRequestsPerHostintegerstring

Max concurrent HTTP requests per host

Caps concurrent HTTP requests to a single host (the API server). Fabric8 default: 5.

namespacestring

Default namespace

Namespace used when resources omit a namespace.

oauthTokenstring

OAuth token

oauthTokenProvider

Dynamically refreshes the OAuth token used to authenticate with the Kubernetes API. Use this when authenticating via a cloud provider (e.g. GCP, AWS, Azure) whose tokens are short-lived (typically 1 hour). Without this, long-running tasks will fail with an unauthorized error once the initial token expires. The provider executes a Kestra task to fetch a fresh token each time the Kubernetes client needs to re-authenticate.

Dynamically refreshes an OAuth token by executing a Kestra task each time the Kubernetes client needs to authenticate. This is essential for cloud providers (e.g. GCP, AWS, Azure) whose tokens are short-lived (typically 1 hour). Without automatic refresh, long-running tasks will fail with an unauthorized error once the initial token expires.

cachestring
DefaultPT5M
Formatduration

Token cache duration

How long a fetched token is reused before the provider executes the task again. Caching avoids hammering the token endpoint on every Kubernetes API call. Defaults to 5 minutes (PT5M). Set to PT0S to disable caching.

outputstring

Token output expression

An expression to extract the token value from the task output, e.g. {{ accessToken.tokenValue }}.

task

Token provider task

A Kestra task that fetches a fresh OAuth token. This task is executed each time the Kubernetes client needs to authenticate, enabling automatic token refresh for long-running operations.

passwordstring

Password

trustCertsbooleanstring

Trust all certificates

When true, skips TLS cert validation. Use only for testing.

trustStoreFilestring

Truststore file

trustStorePassphrasestring

Truststore passphrase

usernamestring

Username

watchReconnectIntervalstring

Watch reconnect interval

Backoff between watch reconnect attempts. Increase to prevent reconnect storms under API server pressure. Fabric8 default: 1s.

websocketPingIntervalstring

WebSocket ping interval

Keepalive ping on exec/log connections so idle streams aren't dropped by a proxy (e.g. GKE konnectivity). Only honored by the OkHttp backend. 0 disables.

Defaultfalse

Inherit ambient cluster configuration

When true, connection is layered on top of the ambient auto-configuration (system properties, environment, kubeconfig, in-cluster service account) instead of starting from blank.

DefaultPT1M
Formatduration

Polling interval

ISO-8601 duration between two reads of the cluster.

Kubeconfig context

Context to select from kubeconfig, or from the worker's ambient kubeconfig when neither kubeconfig nor connection is set.

Raw kubeconfig content

A complete kubeconfig. Mutually exclusive with connection. Supply through {{ secret('...') }} rather than inline.

Unlike the tasks, which hand the kubeconfig to helm inside a container, the trigger loads it on the Kestra worker, so it must carry its credentials inline: exec, auth-provider, tokenFile, client-certificate, client-key, and certificate-authority are rejected. Use the *-data fields and a token, or connection with an oauthTokenProvider for short-lived cloud credentials such as EKS or GKE.

Defaultdefault

Kubernetes namespace

Namespace whose releases are watched. Ignored when allNamespaces is true.

DefaultCREATE_OR_UPDATE
Possible Values
CREATEUPDATECREATE_OR_UPDATE

Trigger event type

  • CREATE: fires for releases the trigger has not seen before.
  • UPDATE: fires when a release it has already seen moves to a new revision or status.
  • CREATE_OR_UPDATE: fires on either.

Release name

Watches only the release with this exact name, which must be a valid Helm release name. Mutually exclusive with releaseNamePattern.

Release name pattern

Watches only releases whose name matches this regular expression in full. Mutually exclusive with releaseName. At most 256 characters, and a repeated group must not itself contain a quantifier or an alternation, such as (a+)+ or (a|aa)+. This is a best-effort guard against patterns that backtrack catastrophically on every poll, not a guarantee, so keep patterns simple.

State key

KV key under which the last seen revision and status of each release is stored. Defaults to <namespace>_<flowId>_<triggerId>.

State TTL

How long a release is remembered without being listed by a poll, e.g. P30D. Releases that are no longer on the cluster are forgotten on the next poll regardless, so this only matters when the trigger stops polling for longer than the TTL: every release then fires again as new.

SubTypestring
Possible Values
UNKNOWNDEPLOYEDUNINSTALLEDSUPERSEDEDFAILEDUNINSTALLINGPENDING_INSTALLPENDING_UPGRADEPENDING_ROLLBACK

Statuses to fire on

Fires only when the latest revision of a release is in one of these statuses. Every status fires when unset.

SubTypestring
Possible Values
CREATEDSUBMITTEDRUNNINGPAUSEDRESTARTEDKILLINGSUCCESSWARNINGFAILEDKILLEDCANCELLEDQUEUEDRETRYINGRETRIEDSKIPPEDBREAKPOINTRESUBMITTED

List of execution states after which a trigger should be stopped (a.k.a. disabled).

Minimum time in a pending status

When set, a release in PENDING_INSTALL, PENDING_UPGRADE, or PENDING_ROLLBACK fires only once it has been pending for longer than this, which tells a stuck operation apart from one still running. Other statuses are unaffected.

Defaulttrue

A condition that determines whether the trigger should run.

A Pebble expression evaluated at trigger time. The trigger fires only when the expression evaluates to a truthy value (true, a non-empty string, a non-zero number). Use this to gate trigger execution on dynamic runtime values such as execution labels, flow variables, or environment conditions.

Number of releases that changed state

Releases that changed state

Definitions
appVersionstring

Application version

chartstring

Chart name

chartVersionstring

Chart version

clusterstring

Cluster name

The cluster property, or the host of the Kubernetes API server when connection is used. Null otherwise.

descriptionstring

Revision description

Helm's summary of the last operation, e.g. Upgrade complete, or the error that failed it.

firstDeployedstring
Formatdate-time

First deployment time

lastDeployedstring
Formatdate-time

Last deployment time

namespacestring

Namespace holding the release

previousStatusstring

Previous status

Status the trigger last recorded for this release. Null the first time the release is seen.

releaseNamestring

Release name

revisioninteger

Revision of the release now current

statusstring

Release status

Helm status of the current revision, such as deployed, failed, or pending-upgrade.