Skip to content

Validate and Ship

FieldValue
TypeSkill Resource
Source~/.copilot/skills/platform/references/helm/validate.md
DescriptionNot specified

Source Content

Validate and Ship

Two gates before any chart is committed: helm lint for chart-structure problems and helm template | kubeconform for manifest-schema problems. Then the chart deploys through ArgoCD, not a manual helm install in production.

Contents

Lint

Terminal window
helm lint ./chart --values values.yaml --values values-dev.yaml

Run lint with each environment’s values layered on the base, because an env override can introduce a value the base never exercised. Fix every error and every warning.

Template and kubeconform

Render the chart and validate the output against the Kubernetes OpenAPI schemas. This catches bad apiVersions, missing required fields, and typo’d keys that lint does not.

Terminal window
helm template app ./chart \
--values values.yaml \
--values values-prod.yaml \
| kubeconform -strict -summary -ignore-missing-schemas
  • -strict rejects unknown fields — the whole point.
  • -ignore-missing-schemas skips CRs whose CRD schema is not bundled; pair with -schema-location to validate against installed CRDs when needed.
  • kubectl apply --dry-run=server is the server-side alternative when the cluster is reachable.

Both helm lint and the kubeconform pass must be clean before commit.

One-command check

scripts/lint_chart.sh runs both gates above plus the house-rule checks from SKILL.md — CRD opt-out key present when the chart ships crds/, no floating latest version/tag in Chart.yaml or values files, and no plaintext-looking secret value in a values file. helm/kubeconform missing on PATH degrades that half of the check to a warning instead of blocking the house-rule checks, so it still runs somewhere without the CLIs installed.

Terminal window
scripts/lint_chart.sh ./chart values.yaml values-prod.yaml

A non-zero exit means at least one ❌ line above needs fixing before commit.

The ArgoCD Application

Charts deploy via GitOps. The Application pins an exact targetRevision — never a floating ref.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/dmwd-io/infra.git
targetRevision: v1.4.0 # pinned — never HEAD or a branch
path: charts/app
helm:
valueFiles:
- values.yaml
- values-prod.yaml
destination:
server: https://kubernetes.default.svc
namespace: p3-app # p3-* platform namespace (ADR-028)
syncPolicy:
automated:
prune: true
selfHeal: true

ArgoCD does not own CRD lifecycle. CRDs are applied by the kubectl task before the Application syncs (see crd-ordering.md). Do not add CRDs to the app-of-apps sync.

Secrets

No plaintext secret ever lands in a values file or a committed manifest. Values files carry references:

  • 1Password Connect via external-secrets ExternalSecret resources that resolve to a Secret at runtime.
  • The chart mounts the resulting Secret; the chart repo never holds the value.

A secret committed to git is a security incident, not a lint warning — treat it as one.