Skip to main content
Install a Helm chart from a forma, alongside the rest of your Kubernetes resources, with no separate helm install step and no Helm CLI on the machine. K8S::Helm::Release hands the chart to Helm and manages the resulting release as one formae resource.

The model

formae manages the release. Helm manages the objects the chart renders. That split is the whole point. Hooks, hook weights, hook delete policies, CRD install ordering and revision history are Helm behaviours, and the plugin gets all of them by calling Helm rather than reimplementing them. A chart with a pre-install Job runs that Job, at the right moment, once. The objects a release renders are hidden from discovery: the release stands in for them, and lists what it owns on resourceNames. Objects created downstream of the chart by controllers (the Pods behind a Deployment, the Jobs behind a CronJob) are not in the rendered manifest and are still discovered individually.

Prerequisites

A reachable cluster. That is all. The plugin embeds the Helm SDK, so there is no helm binary to install, no helm repo add, and no Pkl reader on your PATH. Chart repositories are resolved from repoURL at apply time.

The forma

This installs Flux (controllers plus 14 CRDs) as one release. Helm installs the CRDs before the controllers that need them, which is exactly the ordering a client-side render could not express.
Apply it with one command:
namespace = fluxNs.res.name is a reference, so formae orders the namespace before the release without any explicit dependency declaration.

Release fields

revision, status, appVersion and resourceNames are reported by the provider, not set by you. A bare chart with no repoURL is rejected up front, naming the fix, rather than failing later against the cluster.

What is not modelled

  • helm rollback. Revert the values in your forma and re-apply. Note this fires pre-upgrade hooks, not pre-rollback hooks.
  • helm test. A CI verb, not desired state.
  • Drift inside the release. Editing a chart-owned Deployment by hand is invisible here, exactly as it is invisible to Helm itself.
  • Uninstall residue. Objects from the chart’s crds/ directory, and any object annotated helm.sh/resource-policy: keep, outlive a delete and correctly reappear as unmanaged once no release claims them.

Migrating from HelmChart

HelmChart.pkl and its per-version wrapper trees were removed in the Kubernetes plugin 0.1.11. If you import @formae-helm/v<X.Y>/HelmChart.pkl or @k8s/helm/v<X.Y>/HelmChart.pkl, that import no longer resolves. The old model rendered a chart client-side with helm template and decomposed it into individual typed formae resources. It gave you per-object state, but it could not honour hooks at all: a pre-install Job became a permanent resource that never re-ran, hook-weight was ignored, finished hooks accumulated, and test hooks were applied on every reconcile. Charts that relied on hooks applied silently wrong, which is a worse failure than not being supported. It was removed rather than deprecated for that reason. There is no mechanical rewrite. HelmChart produced N resources in formae state and Release produces one, so the release adopts what the chart already installed rather than inheriting per-object state:
  1. Replace the HelmChart block with a helm.Release naming the same chart, version and values.
  2. Drop the @formae-helm/* import, the pkl-readers/helm package dependency and the pkl-reader-helm external-reader declaration. Nothing renders a chart at Pkl-eval time any more.
  3. Apply. The release adopts the existing objects; the per-object rows leave formae state.
A release this plugin did not install is refused rather than adopted silently, so an accidental name collision fails loudly.
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

K8S::Helm::Release ships at the root of the Kubernetes plugin’s Pkl package as @k8s/helm/Release.pkl. See formae-plugin-kubernetes.