Files
helmfile/docs/hooks.md
T
yxxhero e703b15075 docs: restructure documentation and improve newcomer experience (#2573)
* feat: add --write-output flag to helmfile fetch for air-gapped environments

Add --write-output flag to helmfile fetch that outputs a modified
helmfile.yaml with chart references updated to point to downloaded
local chart paths. Combined with --output-dir, this enables preparing
all charts for deployment in air-gapped environments.

Usage:
  helmfile fetch --output-dir ./charts --write-output > helmfile-airgapped.yaml

Fixes #2571

Signed-off-by: yxxhero <yxxhero@users.noreply.github.com>
Signed-off-by: yxxhero <aiopsclub@163.com>

* docs: restructure documentation and improve newcomer experience

Split the monolithic index.md (1990 lines) into focused topic pages,
update mkdocs.yml navigation, and add missing documentation for
undocumented code features.

Structure changes:
- Extract configuration.md (helmfile.yaml reference)
- Extract cli.md (CLI commands and flags)
- Extract templating.md (template syntax and env vars)
- Extract environments.md (environment configuration)
- Extract releases.md (DAG, needs, selectors)
- Extract hooks.md (lifecycle hooks)
- Extract integrations.md (ArgoCD, Azure ACR, OCI)
- Slim index.md to ~270 line landing page with step-by-step tutorial

Newcomer improvements:
- Add 5-step Getting Started tutorial with explanations
- Reorganize nav: Getting Started now shows core learning path
  (Writing Helmfile → Values → Environments → Releases)
- Add Quick Reference table to configuration.md
- Simplify writing-helmfile.md title

Code-vs-docs gap fixes:
- Document 23 undocumented release fields (valuesTemplate,
  setTemplate, forceNamespace, adopt, trackMode, etc.)
- Document 6 undocumented helmDefaults fields (enableDNS,
  forceConflicts, skipRefresh, takeOwnership, etc.)
- Document print-env command and missing CLI flags
- Document kubectlApply hook field
- Document environment defaults field and merge order
- Document kubedogQPS/kubedogBurst advanced settings
- Document template partials (_*.tpl) auto-loading

Cleanup:
- Fix Docker image version from v0.156.0 to v1.1.0
- Fix heading nesting in advanced-features.md
- Update experimental-features.md with current features
- Fix broken cross-references and anchor links

Signed-off-by: yxxhero <aiopsclub@163.com>

* Revert changes to pkg/app from docs/restructure-and-improve branch

Signed-off-by: yxxhero <aiopsclub@163.com>

* docs: add create subcommand to README and CLI reference

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <yxxhero@users.noreply.github.com>
Signed-off-by: yxxhero <aiopsclub@163.com>
2026-05-03 19:33:33 +08:00

295 lines
9.5 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Hooks
## Hooks
A Helmfile hook is a per-release extension point that is composed of:
* `events`
* `command`
* `args`
* `showlogs`
* `kubectlApply` (alternative to `command`/`args`)
Helmfile triggers various `events` while it is running.
Once `events` are triggered, associated `hooks` are executed, by running the `command` with `args`. The standard output of the `command` will be displayed if `showlogs` is set and it's value is `true`.
Hooks exec order follows the order of definition in the helmfile state.
Currently supported `events` are:
* `prepare`
* `preapply`
* `presync`
* `preuninstall`
* `postuninstall`
* `postsync`
* `cleanup`
Hooks associated to `prepare` events are triggered after each release in your helmfile is loaded from YAML, before execution.
`prepare` hooks are triggered on the release as long as it is not excluded by the helmfile selector(e.g. `helmfile -l key=value`).
Hooks associated to `presync` events are triggered before each release is synced (installed or upgraded) on the cluster.
This is the ideal event to execute any commands that may mutate the cluster state as it will not be run for read-only operations like `lint`, `diff` or `template`.
`preapply` hooks are triggered before a release is uninstalled, installed, or upgraded as part of `helmfile apply`.
This is the ideal event to hook into when you are going to use `helmfile apply` for every kind of change. Note that preapply hooks will only run if at least one release has changes to apply. Be sure to make each `preapply` hook command idempotent. Otherwise, rerunning `helmfile apply` on a transient failure may end up either breaking your cluster, or the hook that runs for the second time will never succeed.
`preuninstall` hooks are triggered immediately before a release is uninstalled as part of `helmfile apply`, `helmfile sync`, `helmfile delete`, and `helmfile destroy`.
`postuninstall` hooks are triggered immediately after successful uninstall of a release while running `helmfile apply`, `helmfile sync`, `helmfile delete`, `helmfile destroy`.
`postsync` hooks are triggered after each release is synced (installed or upgraded) on the cluster, regardless if the sync was successful or not.
This is the ideal place to execute any commands that may mutate the cluster state as it will not be run for read-only operations like `lint`, `diff` or `template`.
`cleanup` hooks are triggered after each release is processed.
This is the counterpart to `prepare`, as any release on which `prepare` has been triggered gets `cleanup` triggered as well.
The following is an example hook that just prints the contextual information provided to hook:
```yaml
releases:
- name: myapp
chart: mychart
# *snip*
hooks:
- events: ["prepare", "cleanup"]
showlogs: true
command: "echo"
args: ["{{`{{.Environment.Name}}`}}", "{{`{{.Release.Name}}`}}", "{{`{{.HelmfileCommand}}`}}\
"]
```
Let's say you ran `helmfile --environment prod sync`, the above hook results in executing:
```
echo {{Environment.Name}} {{.Release.Name}} {{.HelmfileCommand}}
```
Whereas the template expressions are executed thus the command becomes:
```
echo prod myapp sync
```
Now, replace `echo` with any command you like, and rewrite `args` that actually conforms to the command, so that you can integrate any command that does:
* templating
* linting
* testing
Hooks expose additional template expressions:
`.Event.Name` is the name of the hook event.
`.Event.Error` is the error generated by a failed release, exposed for `postsync` hooks only when a release fails, otherwise its value is `nil`.
You can use the hooks event expressions to send notifications to platforms such as `Slack`, `MS Teams`, etc.
The following example passes arguments to a script which sends a notification:
```yaml
releases:
- name: myapp
chart: mychart
# *snip*
hooks:
- events:
- presync
- postsync
showlogs: true
command: notify.sh
args:
- --event
- '{{`{{ .Event.Name }}`}}'
- --status
- '{{`{{ if .Event.Error }}failure{{ else }}success{{ end }}`}}'
- --environment
- '{{`{{ .Environment.Name }}`}}'
- --namespace
- '{{`{{ .Release.Namespace }}`}}'
- --release
- '{{`{{ .Release.Name }}`}}'
```
For templating, imagine that you created a hook that generates a helm chart on-the-fly by running an external tool like ksonnet, kustomize, or your own template engine.
It will allow you to write your helm releases with any language you like, while still leveraging goodies provided by helm.
### Hooks, Kubectl and Environments
Hooks can also be used in combination with small tasks using `kubectl` directly,
e.g.: in order to install a custom storage class.
In the following example, a specific release depends on a custom storage class.
Further, all enviroments have a default kube context configured where releases are deployed into.
The `.Environment.KubeContext` is used in order to apply / remove the YAML to the correct context depending on the environment.
`environments.yaml`:
```yaml
environments:
dev:
values:
- ../values/default.yaml
- ../values/dev.yaml
kubeContext: dev-cluster
prod:
values:
- ../values/default.yaml
- ../values/prod.yaml
kubeContext: prod-cluster
```
`helmfile.yaml`:
```yaml
bases:
- ./environments.yaml
---
releases:
- name: myService
namespace: my-ns
installed: true
chart: mychart
version: "1.2.3"
values:
- ../services/my-service/values.yaml.gotmpl
hooks:
- events: ["presync"]
showlogs: true
command: "kubectl"
args:
- "apply"
- "-f"
- "./custom-storage-class.yaml"
- "--context"
- "{{`{{.Environment.KubeContext}}`}}"
- events: ["postuninstall"]
showlogs: true
command: "kubectl"
args:
- "delete"
- "-f"
- "./custom-storage-class.yaml"
- "--context"
- "{{`{{.Environment.KubeContext}}`}}"
```
### Global Hooks
In contrast to the per release hooks mentioned above these are run only once at the very beginning and end of the execution of a helmfile command and only the `prepare` and `cleanup` hooks are available respectively.
They use the same syntax as per release hooks, but at the top level of your helmfile:
```yaml
hooks:
- events: ["prepare", "cleanup"]
showlogs: true
command: "echo"
args: ["{{`{{.Environment.Name}}`}}", "{{`{{.HelmfileCommand}}`}}\
"]
```
### Helmfile + Kustomize
Do you prefer `kustomize` to write and organize your Kubernetes apps, but still want to leverage helm's useful features
like rollback, history, and so on? This section is for you!
The combination of `hooks` and [helmify-kustomize](https://gist.github.com/mumoshu/f9d0bd98e0eb77f636f79fc2fb130690)
enables you to integrate [kustomize](https://github.com/kubernetes-sigs/kustomize) into Helmfile.
That is, you can use `kustomize` to build a local helm chart from a kustomize overlay.
Let's assume you have a kustomize project named `foo-kustomize` like this:
```
foo-kustomize/
├── base
│   ├── configMap.yaml
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
└── overlays
├── default
│   ├── kustomization.yaml
│   └── map.yaml
├── production
│   ├── deployment.yaml
│   └── kustomization.yaml
└── staging
├── kustomization.yaml
└── map.yaml
5 directories, 10 files
```
Write `helmfile.yaml`:
```yaml
- name: kustomize
chart: ./foo
hooks:
- events: ["prepare", "cleanup"]
command: "../helmify"
args: ["{{`{{if eq .Event.Name \"prepare\"}}build{{else}}clean{{end}}`}}", "{{`{{.Release.Ch\
art}}`}}", "{{`{{.Environment.Name}}`}}"]
```
Run `helmfile --environment staging sync` and see it results in helmfile running `kustomize build foo-kustomize/overlays/staging > foo/templates/all.yaml`.
Voilà! You can mix helm releases that are backed by remote charts, local charts, and even kustomize overlays.
### kubectlApply Hook
Instead of specifying `command` and `args`, you can use the `kubectlApply` field to run `kubectl apply` directly:
```yaml
releases:
- name: myapp
chart: mychart
hooks:
- events: ["presync"]
showlogs: true
kubectlApply:
filename: manifests/custom-resource.yaml
```
Or apply a kustomize overlay:
```yaml
hooks:
- events: ["presync"]
showlogs: true
kubectlApply:
kustomize: overlays/default/
```
The `kubectlApply` field accepts either:
* `filename:` - runs `kubectl apply -f <value>`
* `kustomize:` - runs `kubectl apply -k <value>`
**Note:** `filename` and `kustomize` cannot be used together. When `kubectlApply` is set, the `command` field is ignored with a warning.
### Hook Template Data
Hooks have access to the following template data:
Per-release hooks:
* `{{ .Environment.Name }}` - the environment name
* `{{ .Environment.KubeContext }}` - the environment kube context
* `{{ .Release.Name }}` - the release name
* `{{ .Release.Namespace }}` - the release namespace
* `{{ .Release.Labels }}` - the release labels
* `{{ .Release.Chart }}` - the release chart
* `{{ .Values }}` - state values
* `{{ .HelmfileCommand }}` - the helmfile command name (e.g., `sync`, `apply`)
* `{{ .Event.Name }}` - the hook event name
* `{{ .Event.Error }}` - the error (available in `postsync` hooks when a release fails)
Global hooks:
* `{{ .Environment.Name }}` - the environment name
* `{{ .HelmfileCommand }}` - the helmfile command name
* `{{ .Event.Name }}` - the hook event name
* `{{ .Event.Error }}` - the error