Claude Agent Skill · by Wshobson

Helm Chart Scaffolding

Creates proper Helm chart structure with Chart.yaml metadata, hierarchical values.yaml organization, and templated Kubernetes manifests. Handles the tedious sca

Install
Terminal · npx
$npx skills add https://github.com/wshobson/agents --skill helm-chart-scaffolding
Works with Paperclip

How Helm Chart Scaffolding fits into a Paperclip company.

Helm Chart Scaffolding drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md560 lines
Expand
---name: helm-chart-scaffoldingdescription: Design, organize, and manage Helm charts for templating and packaging Kubernetes applications with reusable configurations. Use when creating Helm charts, packaging Kubernetes applications, or implementing templated deployments.--- # Helm Chart Scaffolding Comprehensive guidance for creating, organizing, and managing Helm charts for packaging and deploying Kubernetes applications. ## Purpose This skill provides step-by-step instructions for building production-ready Helm charts, including chart structure, templating patterns, values management, and validation strategies. ## When to Use This Skill Use this skill when you need to: - Create new Helm charts from scratch- Package Kubernetes applications for distribution- Manage multi-environment deployments with Helm- Implement templating for reusable Kubernetes manifests- Set up Helm chart repositories- Follow Helm best practices and conventions ## Helm Overview **Helm** is the package manager for Kubernetes that: - Templates Kubernetes manifests for reusability- Manages application releases and rollbacks- Handles dependencies between charts- Provides version control for deployments- Simplifies configuration management across environments ## Step-by-Step Workflow ### 1. Initialize Chart Structure **Create new chart:** ```bashhelm create my-app``` **Standard chart structure:** ```my-app/├── Chart.yaml           # Chart metadata├── values.yaml          # Default configuration values├── charts/              # Chart dependencies├── templates/           # Kubernetes manifest templates│   ├── NOTES.txt       # Post-install notes│   ├── _helpers.tpl    # Template helpers│   ├── deployment.yaml│   ├── service.yaml│   ├── ingress.yaml│   ├── serviceaccount.yaml│   ├── hpa.yaml│   └── tests/│       └── test-connection.yaml└── .helmignore         # Files to ignore``` ### 2. Configure Chart.yaml **Chart metadata defines the package:** ```yamlapiVersion: v2name: my-appdescription: A Helm chart for My Applicationtype: applicationversion: 1.0.0 # Chart versionappVersion: "2.1.0" # Application version # Keywords for chart discoverykeywords:  - web  - api  - backend # Maintainer informationmaintainers:  - name: DevOps Team    email: devops@example.com    url: https://github.com/example/my-app # Source code repositorysources:  - https://github.com/example/my-app # Homepagehome: https://example.com # Chart iconicon: https://example.com/icon.png # Dependenciesdependencies:  - name: postgresql    version: "12.0.0"    repository: "https://charts.bitnami.com/bitnami"    condition: postgresql.enabled  - name: redis    version: "17.0.0"    repository: "https://charts.bitnami.com/bitnami"    condition: redis.enabled``` **Reference:** See `assets/Chart.yaml.template` for complete example ### 3. Design values.yaml Structure **Organize values hierarchically:** ```yaml# Image configurationimage:  repository: myapp  tag: "1.0.0"  pullPolicy: IfNotPresent # Number of replicasreplicaCount: 3 # Service configurationservice:  type: ClusterIP  port: 80  targetPort: 8080 # Ingress configurationingress:  enabled: false  className: nginx  hosts:    - host: app.example.com      paths:        - path: /          pathType: Prefix # Resourcesresources:  requests:    memory: "256Mi"    cpu: "250m"  limits:    memory: "512Mi"    cpu: "500m" # Autoscalingautoscaling:  enabled: false  minReplicas: 2  maxReplicas: 10  targetCPUUtilizationPercentage: 80 # Environment variablesenv:  - name: LOG_LEVEL    value: "info" # ConfigMap dataconfigMap:  data:    APP_MODE: production # Dependenciespostgresql:  enabled: true  auth:    database: myapp    username: myapp redis:  enabled: false``` **Reference:** See `assets/values.yaml.template` for complete structure ### 4. Create Template Files **Use Go templating with Helm functions:** **templates/deployment.yaml:** ```yamlapiVersion: apps/v1kind: Deploymentmetadata:  name: {{ include "my-app.fullname" . }}  labels:    {{- include "my-app.labels" . | nindent 4 }}spec:  {{- if not .Values.autoscaling.enabled }}  replicas: {{ .Values.replicaCount }}  {{- end }}  selector:    matchLabels:      {{- include "my-app.selectorLabels" . | nindent 6 }}  template:    metadata:      labels:        {{- include "my-app.selectorLabels" . | nindent 8 }}    spec:      containers:      - name: {{ .Chart.Name }}        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"        imagePullPolicy: {{ .Values.image.pullPolicy }}        ports:        - name: http          containerPort: {{ .Values.service.targetPort }}        resources:          {{- toYaml .Values.resources | nindent 12 }}        env:          {{- toYaml .Values.env | nindent 12 }}``` ### 5. Create Template Helpers **templates/\_helpers.tpl:** ```yaml{{/*Expand the name of the chart.*/}}{{- define "my-app.name" -}}{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}{{- end }} {{/*Create a default fully qualified app name.*/}}{{- define "my-app.fullname" -}}{{- if .Values.fullnameOverride }}{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}{{- else }}{{- $name := default .Chart.Name .Values.nameOverride }}{{- if contains $name .Release.Name }}{{- .Release.Name | trunc 63 | trimSuffix "-" }}{{- else }}{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}{{- end }}{{- end }}{{- end }} {{/*Common labels*/}}{{- define "my-app.labels" -}}helm.sh/chart: {{ include "my-app.chart" . }}{{ include "my-app.selectorLabels" . }}{{- if .Chart.AppVersion }}app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}{{- end }}app.kubernetes.io/managed-by: {{ .Release.Service }}{{- end }} {{/*Selector labels*/}}{{- define "my-app.selectorLabels" -}}app.kubernetes.io/name: {{ include "my-app.name" . }}app.kubernetes.io/instance: {{ .Release.Name }}{{- end }}``` ### 6. Manage Dependencies **Add dependencies in Chart.yaml:** ```yamldependencies:  - name: postgresql    version: "12.0.0"    repository: "https://charts.bitnami.com/bitnami"    condition: postgresql.enabled``` **Update dependencies:** ```bashhelm dependency updatehelm dependency build``` **Override dependency values:** ```yaml# values.yamlpostgresql:  enabled: true  auth:    database: myapp    username: myapp    password: changeme  primary:    persistence:      enabled: true      size: 10Gi``` ### 7. Test and Validate **Validation commands:** ```bash# Lint the charthelm lint my-app/ # Dry-run installationhelm install my-app ./my-app --dry-run --debug # Template renderinghelm template my-app ./my-app # Template with valueshelm template my-app ./my-app -f values-prod.yaml # Show computed valueshelm show values ./my-app``` **Validation script:** ```bash#!/bin/bashset -e echo "Linting chart..."helm lint . echo "Testing template rendering..."helm template test-release . --dry-run echo "Checking for required values..."helm template test-release . --validate echo "All validations passed!"``` **Reference:** See `scripts/validate-chart.sh` ### 8. Package and Distribute **Package the chart:** ```bashhelm package my-app/# Creates: my-app-1.0.0.tgz``` **Create chart repository:** ```bash# Create indexhelm repo index . # Upload to repository# AWS S3 exampleaws s3 sync . s3://my-helm-charts/ --exclude "*" --include "*.tgz" --include "index.yaml"``` **Use the chart:** ```bashhelm repo add my-repo https://charts.example.comhelm repo updatehelm install my-app my-repo/my-app``` ### 9. Multi-Environment Configuration **Environment-specific values files:** ```my-app/├── values.yaml          # Defaults├── values-dev.yaml      # Development├── values-staging.yaml  # Staging└── values-prod.yaml     # Production``` **values-prod.yaml:** ```yamlreplicaCount: 5 image:  tag: "2.1.0" resources:  requests:    memory: "512Mi"    cpu: "500m"  limits:    memory: "1Gi"    cpu: "1000m" autoscaling:  enabled: true  minReplicas: 3  maxReplicas: 20 ingress:  enabled: true  hosts:    - host: app.example.com      paths:        - path: /          pathType: Prefix postgresql:  enabled: true  primary:    persistence:      size: 100Gi``` **Install with environment:** ```bashhelm install my-app ./my-app -f values-prod.yaml --namespace production``` ### 10. Implement Hooks and Tests **Pre-install hook:** ```yaml# templates/pre-install-job.yamlapiVersion: batch/v1kind: Jobmetadata:  name: {{ include "my-app.fullname" . }}-db-setup  annotations:    "helm.sh/hook": pre-install    "helm.sh/hook-weight": "-5"    "helm.sh/hook-delete-policy": hook-succeededspec:  template:    spec:      containers:      - name: db-setup        image: postgres:15        command: ["psql", "-c", "CREATE DATABASE myapp"]      restartPolicy: Never``` **Test connection:** ```yaml# templates/tests/test-connection.yamlapiVersion: v1kind: Podmetadata:  name: "{{ include "my-app.fullname" . }}-test-connection"  annotations:    "helm.sh/hook": testspec:  containers:  - name: wget    image: busybox    command: ['wget']    args: ['{{ include "my-app.fullname" . }}:{{ .Values.service.port }}']  restartPolicy: Never``` **Run tests:** ```bashhelm test my-app``` ## Common Patterns ### Pattern 1: Conditional Resources ```yaml{{- if .Values.ingress.enabled }}apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: {{ include "my-app.fullname" . }}spec:  # ...{{- end }}``` ### Pattern 2: Iterating Over Lists ```yamlenv:{{- range .Values.env }}- name: {{ .name }}  value: {{ .value | quote }}{{- end }}``` ### Pattern 3: Including Files ```yamldata:  config.yaml: |    {{- .Files.Get "config/application.yaml" | nindent 4 }}``` ### Pattern 4: Global Values ```yamlglobal:  imageRegistry: docker.io  imagePullSecrets:    - name: regcred # Use in templates:image: {{ .Values.global.imageRegistry }}/{{ .Values.image.repository }}``` ## Best Practices 1. **Use semantic versioning** for chart and app versions2. **Document all values** in values.yaml with comments3. **Use template helpers** for repeated logic4. **Validate charts** before packaging5. **Pin dependency versions** explicitly6. **Use conditions** for optional resources7. **Follow naming conventions** (lowercase, hyphens)8. **Include NOTES.txt** with usage instructions9. **Add labels** consistently using helpers10. **Test installations** in all environments ## Troubleshooting **Template rendering errors:** ```bashhelm template my-app ./my-app --debug``` **Dependency issues:** ```bashhelm dependency updatehelm dependency list``` **Installation failures:** ```bashhelm install my-app ./my-app --dry-run --debugkubectl get events --sort-by='.lastTimestamp'```  ## Related Skills - `k8s-manifest-generator` - For creating base Kubernetes manifests- `gitops-workflow` - For automated Helm chart deployments