Helm workflow
Helm chart development and release management including chart structure, values design, template best practices, hooks, dependency management, testing, and repository management. Covers Helm v3/v4 and Kustomize selection. Use when creating, reviewing, or managing Helm charts.From its SKILL.md
npx -y skills add iceflower/agent-skills --skill helm-workflowAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
15.8 KB, ~4.0k tokens by cl100k_base, as published. Nobody here has run it
Helm Workflow Rules
1. Chart Structure
Standard Directory Layout
mychart/
├── Chart.yaml # Chart metadata (required)
├── Chart.lock # Dependency lock file (auto-generated)
├── values.yaml # Default configuration values
├── values.schema.json # JSON Schema for values validation
├── .helmignore # Patterns to ignore when packaging
├── templates/ # Template files
│ ├── _helpers.tpl # Named template definitions
│ ├── NOTES.txt # Post-install usage notes
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── serviceaccount.yaml
│ ├── hpa.yaml
│ └── tests/
│ └── test-connection.yaml
├── charts/ # Dependency charts (auto-populated)
└── crds/ # Custom Resource Definitions
Chart.yaml Conventions
apiVersion: v2
name: myapp
description: A Helm chart for MyApp
type: application # application or library
version: 1.2.0 # Chart version (SemVer)
appVersion: "3.4.1" # Application version
kubeVersion: ">=1.28.0" # Required K8s version constraint
maintainers:
- name: team-platform
email: [email protected]
dependencies:
- name: postgresql
version: "~15.x"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: postgresql.enabled
| Field | Rule |
|---|---|
version | SemVer — bump on every chart change |
appVersion | Match the deployed application version |
kubeVersion | Set minimum K8s version constraint |
type | Use library for shared templates only |
2. Values Design
Organization Principles
# Group by component, not by K8s resource type
replicaCount: 2
image:
repository: myapp
tag: "3.4.1"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8080
ingress:
enabled: false
className: nginx
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
# Sub-chart toggle
postgresql:
enabled: true
Naming Conventions
| Pattern | Example | Purpose |
|---|---|---|
| Boolean toggle | ingress.enabled | Enable/disable features |
| camelCase keys | replicaCount | Helm convention |
| Nested objects | image.repository | Group related config |
| Resource presets | resources.requests.cpu | Standard K8s structure |
Values Schema Validation
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["image", "service"],
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1
},
"image": {
"type": "object",
"required": ["repository"],
"properties": {
"repository": { "type": "string" },
"tag": { "type": "string" }
}
}
}
}
Environment-Specific Values
values/
├── values.yaml # Defaults
├── values-dev.yaml # Dev overrides
├── values-staging.yaml # Staging overrides
└── values-prod.yaml # Production overrides
helm upgrade myapp ./mychart \
-f values.yaml \
-f values-prod.yaml \
--namespace production
3. Template Best Practices
See references/template-patterns.md for detailed patterns including helper templates, template functions, whitespace control, NOTES.txt, and testing examples.
§3.1 Library Charts for Template Sharing
Library charts (type: library) are Helm charts that contain only templates — they produce no Kubernetes resources when rendered. Use them to share common template logic across multiple application charts.
Defining a Library Chart
# lib-chart/Chart.yaml
apiVersion: v2
name: lib-chart
description: Shared Helm templates for platform services
type: library # No resources rendered — templates only
version: 1.0.0
A library chart typically contains:
lib-chart/
├── Chart.yaml # type: library
├── templates/
│ ├── _deployment.tpl # Reusable Deployment template
│ ├── _service.tpl # Reusable Service template
│ ├── _ingress.tpl # Reusable Ingress template
│ └── _helpers.tpl # Shared labels, selectors, names
Consuming a Library Chart
Reference the library chart as a dependency in the parent chart:
# app-a/Chart.yaml
apiVersion: v2
name: app-a
type: application
version: 1.0.0
dependencies:
- name: lib-chart
version: "1.x"
repository: "file://../lib-chart"
# or: repository: "oci://ghcr.io/org/charts"
Then invoke shared templates using include:
# app-a/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "lib-chart.fullname" . }}
labels:
{{- include "lib-chart.labels" . | nindent 4 }}
spec:
{{- include "lib-chart.deploymentSpec" . | nindent 2 }}
When to Use Library Charts
- Multiple services share common template patterns (Deployment, Service, Ingress structure)
- Platform teams want to enforce standard labels, annotations, or resource structures
_helpers.tplhas grown too large — split into purpose-specific library charts- Replacing copy-paste template patterns with reusable chart dependencies
Library Chart Rules
- Library charts must declare
type: library— Helm will skip resource rendering - Library charts should not include
values.yamlwith defaults — consumers provide all values - Version library charts independently — bump when shared templates change
- Use
file://for local development, OCI registries for distribution
4. Release Management
Release Naming
| Element | Convention | Example |
|---|---|---|
| Release name | {app}-{env} or {app} | myapp-prod, myapp |
| Namespace | Match environment | production, staging |
| Chart version | SemVer, bump on change | 1.2.0 → 1.3.0 |
Install and Upgrade Commands
# Install with atomic (auto-rollback on failure)
# Helm v4: --atomic renamed to --rollback-on-failure
helm install myapp ./mychart \
--namespace production \
--create-namespace \
--atomic \
--timeout 5m \
-f values-prod.yaml
# Upgrade with wait (wait for pods ready)
helm upgrade myapp ./mychart \
--namespace production \
--atomic \
--timeout 5m \
--cleanup-on-fail \
-f values-prod.yaml
# Install or upgrade (idempotent)
helm upgrade --install myapp ./mychart \
--namespace production \
--create-namespace \
--atomic \
--timeout 5m \
-f values-prod.yaml
Helm v4 Breaking Changes:
--atomic→--rollback-on-failure,--force→--force-replace. Server-side apply is now the default for new releases. See §11 Helm v4 Migration for details.
Rollback
# View history
helm history myapp -n production
# Rollback to previous revision
helm rollback myapp 0 -n production --wait
# Rollback to specific revision
helm rollback myapp 3 -n production --wait
5. Hook Lifecycle
Available Hooks
| Hook | Timing | Use Case |
|---|---|---|
pre-install | Before resources created | DB migration, prerequisite check |
post-install | After resources created | Seed data, notifications |
pre-upgrade | Before upgrade starts | DB migration, backup |
post-upgrade | After upgrade completes | Cache warm-up, verification |
pre-delete | Before release deleted | Data export, cleanup |
post-delete | After release deleted | External resource cleanup |
pre-rollback | Before rollback | Backup current state |
post-rollback | After rollback | Verify rollback success |
Note:
crd-installhook was removed in Helm v4. Use thecrds/directory for CRD management instead.
Hook Definition
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "mychart.fullname" . }}-db-migrate
annotations:
"helm.sh/hook": pre-upgrade,pre-install
"helm.sh/hook-weight": "-5" # Lower runs first
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
backoffLimit: 3
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["./migrate", "up"]
Hook Delete Policies
| Policy | Behavior |
|---|---|
before-hook-creation | Delete previous hook resource before new one |
hook-succeeded | Delete after hook succeeds |
hook-failed | Delete after hook fails |
6. Dependency Management
Declaring Dependencies
# Chart.yaml
dependencies:
- name: postgresql
version: "~15.5"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: postgresql.enabled
alias: db
- name: redis
version: "~19.x"
repository: "oci://registry-1.docker.io/bitnamicharts"
tags:
- cache
import-values:
- child: master.service
parent: redis.service
Commands
# Download dependencies
helm dependency update ./mychart
# Rebuild Chart.lock
helm dependency build ./mychart
# List dependencies
helm dependency list ./mychart
Sub-Chart Value Override
# values.yaml — override sub-chart values by chart name
postgresql:
enabled: true
auth:
database: myapp
username: myapp
# Using alias
db:
enabled: true
7. Testing
See references/template-patterns.md for testing examples including built-in tests, validation pipeline, and helm-unittest.
8. Security
Chart Signing
# Package and sign
helm package ./mychart --sign --key "my-key" --keyring ~/.gnupg/pubring.gpg
# Verify signature
helm verify mychart-1.2.0.tgz --keyring ~/.gnupg/pubring.gpg
# Install with verification
helm install myapp mychart-1.2.0.tgz --verify --keyring ~/.gnupg/pubring.gpg
RBAC Templates
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
Secrets Handling
- Never store plaintext secrets in
values.yaml - Use
--setor external secret managers for sensitive values - Template secrets from references, not hardcoded values
- Consider
ExternalSecretorSealedSecretCRDs instead of Helm-managed secrets
9. Repository Management
OCI Registry (Recommended)
# Login to OCI registry
helm registry login ghcr.io -u USERNAME
# Push chart
helm push mychart-1.2.0.tgz oci://ghcr.io/org/charts
# Pull chart
helm pull oci://ghcr.io/org/charts/mychart --version 1.2.0
# Install from OCI
helm install myapp oci://ghcr.io/org/charts/mychart --version 1.2.0
Versioning Strategy
| Change Type | Version Bump | Example |
|---|---|---|
| Breaking changes | Major | 1.2.0 → 2.0.0 |
| New features, non-breaking | Minor | 1.2.0 → 1.3.0 |
| Bug fixes, doc updates | Patch | 1.2.0 → 1.2.1 |
- Always bump
versionwhen chart content changes appVersiontracks the deployed application version independently
10. Helm vs Kustomize
| Criteria | Helm | Kustomize |
|---|---|---|
| Parameterization | Values-based templating | Patch-based overlays |
| Packaging | Distributable chart archives | Directory-based |
| Dependency management | Built-in | Manual |
| Release tracking | Built-in (helm history) | External (GitOps) |
| Learning curve | Higher (Go templates) | Lower (YAML patches) |
| Best for | Reusable packages, complex logic | Simple overlays, in-house apps |
When to Use Each
- Helm: Distributing charts to others, complex conditional logic, lifecycle hooks, release management
- Kustomize: Internal applications, simple environment overlays, no templating needed
- Hybrid: Use Helm for packaging + Kustomize for environment overlays (
helm template | kustomize)
11. Helm v4 Migration
Helm v4 (current: v4.1.4) introduces breaking changes from v3. Most charts work without modification, but CLI usage and some behaviors have changed.
Breaking Changes from v3
| v3 Flag / Behavior | v4 Equivalent | Notes |
|---|---|---|
--atomic | --rollback-on-failure | Same behavior, renamed flag |
--force | --force-replace | Same behavior, renamed flag |
helm registry login https://ghcr.io | helm registry login ghcr.io | Domain only, no https:// prefix |
crd-install hook | Use crds/ directory | crd-install hook removed |
| Client-side apply (default) | Server-side apply (default) | New releases use SSA |
| In-process post-renderers | Plugin-based post-renderers only | External binary or plugin required |
New Features in v4
- Wasm-based plugins — optional WebAssembly runtime for custom functionality
- OCI digest support — install charts by digest for supply chain security:
helm install myapp oci://registry/chart --version "sha256:abc..." - Multi-document values — split complex values across multiple YAML files
- Custom template functions — extend Go templates via plugins
- kstatus watcher — improved resource readiness monitoring
- Content-based caching — faster dependency resolution
Argo CD Compatibility
Important: Argo CD (as of v3.3.x) does not fully support Helm v4. Argo CD internally uses Helm 3.x. If Helm v4 is installed locally, the
argocdCLI may produce errors. Track argoproj/argo-cd#27280 for status.
Recommendation: Use Helm v3.x for Argo CD-integrated workflows. Helm v4 can be used for local development and direct CLI operations.
Migration Checklist
- Update CI/CD scripts:
--atomic→--rollback-on-failure,--force→--force-replace - Replace
crd-installhooks withcrds/directory - Update
helm registry loginto use domain names only (nohttps://) - Verify Argo CD compatibility if using GitOps workflows
- Test post-renderer plugins if using custom post-renderers
12. Anti-Patterns
- Using
helm installwithout--atomicin CI/CD — leaves failed releases behind - Hardcoding values in templates instead of using
values.yaml - Not setting
kubeVersionconstraint — chart may deploy to incompatible clusters - Skipping
values.schema.json— no validation on user-supplied values - Using
lookupfunction without fallback — breakshelm template - Not bumping chart
versionon changes — cache serves stale charts - Storing secrets in
values.yamlcommitted to VCS - Deeply nested values without documentation — users cannot discover options
- Using
helm installinstead ofhelm upgrade --install— not idempotent - Ignoring
helm lintandhelm templatein CI — catches errors too late
Related Skills
- For Argo CD + Helm integration (App of Apps, helm diff sync, Image Updater, Helm values overrides), see gitops-argocd skill — Argo CD + Helm integration is primarily handled in gitops-argocd
- For Kubernetes manifest conventions and best practices, see k8s-workflow skill
- For secret management in Helm charts, see secrets-management skill
What ships with it: 3 files
15.9 KB alongside SKILL.md, 1 of them executable
references/
- template-patterns.md5.6 KB
scripts/
- lint_chart.pyruns10.1 KB
- README.md201 B