Ready checks see history edit this page

Talks about: , , and

Ready checks decide when a stage is healthy enough to let the next stage start. They are purely observational — the controller waits and reports, but takes no action (active steps are actions ).

By default, with no readyChecks block, the controller waits for every object the stage applied to report ready via kstatus . readyChecks lets you narrow that to specific objects (checks), add custom health for resources kstatus doesn’t understand (exprs, CEL ), bound the wait (timeout), or skip it entirely (disableWait). checks and exprs may be set together.

readyChecks.timeout is the most specific timeout a stage can carry: it wins over stages[].timeout, spec.timeout, and the built-in 15-minute default, and it bounds the whole verify phase — the kstatus wait, the explicit checks, and the exprs evaluated after them. Set it on the one stage whose readiness needs the patience; use the coarser levels when every stage of a run needs the same bound.

Explicit objects

Wait for named objects only — useful when a stage applies many objects but only a few gate the next stage:

spec:
  stages:
    - name: infrastructure
      sourceRef:
        name: platform
      readyChecks:
        timeout: 20m
        checks:
          - apiVersion: apiextensions.k8s.io/v1
            kind: CustomResourceDefinition
            name: ledgers.payments.example
          - apiVersion: apps/v1
            kind: Deployment
            name: ledger-operator
            namespace: platform-system

Cluster-scoped kinds work here — the CustomResourceDefinition above is the common one, and ClusterRole, Namespace, PersistentVolume, and StorageClass behave the same. Leave namespace unset for them; a cluster-scoped object has none, and the field is ignored if you set one anyway. For a namespaced kind, namespace defaults to the StageSet’s when omitted.

This is the gate behind the usual ordering: an early stage installs an operator and its CRDs, a check on the CRD holds the rollout until the API is served, and a later stage applies the custom resources that need it.

Scope is resolved against the cluster the stage targets, so a stage with spec.kubeConfig is judged by the remote cluster’s own API surface.

Custom health with CEL

For custom resources kstatus doesn’t understand, describe readiness with CEL expressions. The shape matches kustomize-controller’s healthCheckExprs, so expressions are portable.

      readyChecks:
        exprs:
          - apiVersion: db.example/v1
            kind: Database
            current: "status.phase == 'Running'"
            inProgress: "status.phase in ['Pending', 'Provisioning']"
            failed: "status.phase == 'Failed'"

The three expressions divide the outcome:

ExpressionMeaning
currentthe object is ready and the stage may advance
inProgressthe object is not ready yet but is still converging
failedthe object will not become ready; the stage fails immediately

inProgress decides what a timeout means. A stage whose objects are still converging when the verify timeout elapses reports StageProgressing and is re-verified on the next reconcile — a slow provision converges unattended and is never rolled back. An object that is neither current nor inProgress is stuck, so the timeout fails the stage. Omit inProgress and every timeout is a failure, which is the right default for a resource that has no meaningful in-between state.

onTimeout: Rollback overrides the hold: set it on the stage (or the StageSet) when a slow object should be reverted rather than waited out.

Opting out

To apply a stage without waiting for readiness (fire-and-forget), disable the wait:

      readyChecks:
        disableWait: true