Skip to main content
Use Helm charts inside a forma. Reference a chart by name and version, set values inline, and apply it alongside the rest of your Kubernetes resources, with no separate helm install step. formae expands the chart into individual managed resources, so a release reconciles, drifts, and tears down like everything else.

Scope and limitations

formae renders a chart (helm template, via pkl-reader-helm) into individual Kubernetes resources at evaluation time, then manages those resources like any other forma. It does not run helm install, so there is no Helm release: the chart’s manifests become plain formae-managed objects, reconciled and drift-corrected by the agent. That model means several Helm features are not supported:
  • Helm hooks are not honored. Resources annotated with helm.sh/hook (pre-install, post-install, pre-upgrade, post-upgrade, pre-delete, post-delete) are rendered as ordinary resources and applied together with everything else. There is no hook ordering, no run-once-then-forget behavior, and no post-completion cleanup; helm.sh/hook-weight and helm.sh/hook-delete-policy are ignored. A chart that depends on a hook Job to initialize state (migrations, CRD installation, secret generation) may not behave as it does under helm install.
  • Chart tests are not run. A helm.sh/hook: test pod is treated as a normal resource (created and left in place), not executed as a test. There is no helm test equivalent.
  • No Helm release lifecycle. There is no release history, no helm rollback, no helm list, and no release-tracking Secret/ConfigMap. Rollback, waiting for readiness, and atomic apply are handled by formae’s own reconcile and drift correction; the Helm flags --wait, --timeout, and --atomic have no analog.
  • No Helm ownership metadata. Resources are not stamped with app.kubernetes.io/managed-by: Helm or Helm release annotations; releaseName is used only as a formae label prefix.
  • helm.sh/resource-policy: keep is ignored. formae’s reconcile owns deletion, so a resource the chart marks keep is still removed if a reconcile no longer declares it.
  • CRDs shipped under a chart’s crds/ directory may not render. helm template does not emit crds/ by default, and there is no --include-crds toggle. CRDs a chart templates under templates/ do render (mapped to a custom resource); CRDs in crds/ should be applied separately.
  • Rendering has no cluster access. Because the chart is templated at evaluation time (not against your cluster), lookup() returns empty and .Capabilities reflect Helm’s defaults rather than your live cluster’s API versions. Charts whose output branches on live cluster state render as if the cluster were empty. (Version alignment is instead enforced by the version coupling below.)
  • The namespace is not created for you. There is no --create-namespace; declare the target namespace as its own resource in the forma (as in the forma below).
If your chart relies on any of the above, prefer breaking it into explicit formae resources, or run those pieces (hook Jobs, CRD installation) as a separate step.

Prerequisites

  • pkl 0.30 or newer.
  • pkl-reader-helm on your PATH, from the apple/pkl-readers releases (look for helm@<ver> tags).
  • helm 3 or newer, with the chart repositories you reference added:
  • A @formae-helm/v<X.Y> import that lines up with your target’s kubernetesVersion and the @k8s/v<X.Y> imports in the same forma. See Version coupling.

The forma

Deploy and tear down. ...chart.resources spreads the chart’s rendered objects into the forma, so they apply and reconcile with everything else:

HelmChart fields

Version coupling

Three things must agree, or pkl eval fails before any cluster call:
  • the @formae-helm/v<X.Y> import,
  • the @k8s/v<X.Y> imports, and
  • Config.kubernetesVersion = "<X.Y>".
To run the same chart against several Kubernetes minors, write one forma per minor or parameterize the file with Pkl properties. If a chart emits a kind your Kubernetes minor does not have (for example FlowSchema against a 1.28 cluster), the integration drops it by default. Set skipUnsupported = false to fail at eval time instead.
This page is about using formae to manage other Helm charts. Installing formae itself through a Helm chart is a different task, covered in Install the agent with Helm.

Source

The HelmChart type ships as the formae-helm Pkl package on the hub. See formae-plugin-k8s/helm.