Skip to content

fix(render): preserve null chart defaults so helm-guarded keys match Argo CD#157

Merged
sholdee merged 4 commits into
mainfrom
feat/item-c-serialization
Jun 16, 2026
Merged

fix(render): preserve null chart defaults so helm-guarded keys match Argo CD#157
sholdee merged 4 commits into
mainfrom
feat/item-c-serialization

Conversation

@sholdee

@sholdee sholdee commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary

Argo CD's repo-server bundles helm v3, which retains null chart defaults in .Values. Helm v4's CoalesceValues (used by ToRenderValuesWithSchemaValidation) strips them via cleanNilValues, so {{- if hasKey .Values "x" }} guards evaluate false under drydock while evaluating true under Argo CD — the key renders in Argo CD but is absent in drydock.

Fix: replace CoalesceValues with MergeValues (nil-preserving) + a separate ValidateAgainstSchema call (internal/render/helm.go). Verified line-by-line against helm v4.2.1 coalesce.go: the two paths differ only in nil-handling; subchart/global/table coalescing is identical, and the engine rebuilds Files/Subcharts/Template itself, so the reconstructed render values map is faithful. Single call site.

Home-ops live-fleet validation (cilium, before/after)

  • Before: debug-verbose, nodeport-addresses, policy-cidr-match-mode missing from drydock's cilium-config (+ 2 cilium.io/cilium-configmap-checksum cascade diffs on DaemonSet cilium / Deployment cilium-operator).
  • After: all 3 keys restored as empty string "", matching Argo CD's helm v3 output (verified against argocd v3.4.3 managed fields).
  • Whole-fleet before/after diff: ONLY those 5 changes — 928→928 resources, no other application affected. The MergeValues swap has no unintended blast radius.

Sweep tooling (test:, not changelog)

  • cleanupEmptyMetaMaps (internal/paritycompare/compare.go): removes empty annotations/labels maps left after the ignore-rule strips argocd.argoproj.io/tracking-id — retires ~700 false diffs (drydock correctly emits tracking-id like real Argo CD; the raw oracle lacks it).
  • trimStringScalars: right-trims trailing \n from string scalars — the oracle's yq re-serialization appends \n to block scalars that drydock's faithful helm-Go-engine value lacks (cert-manager .data.config.yaml, velero .data.global).
  • Dropped --discover-kustomize from scripts/home-ops-live-parity.sh: home-ops #3229 added explicit metadata.namespace: argocd, so default discovery resolves argocd/<name> directly (no more re-rendering the argo-cd chart every run). Caveat: valid only when the live cluster is synced at/after #3229; otherwise apps under-resolve as capture failures (not silent wrong results).
  • parity-helm-null-default smoke fixture (testdata/argocd-parity/) added + registered in argocd-parity-smoke.sh — the lasting CI real-Argo-CD guard for this behavior.

Caveats

  • Helm-version coupling: this matches Argo CD on helm v3 (null-retention). Revisit/retire when Argo CD's repo-server moves to helm v4 — both sides would then strip nulls.
  • Schema validation: ValidateAgainstSchema now sees null values where CoalesceValues silently dropped them. A chart with a type: string field lacking nullable: true and a null default would now fail validation (such a chart would already fail required checks; this is correct behavior).

Test plan

  • go test ./internal/... ./pkg/... ./pr-action/... — pass
  • go vet ./... / golangci-lint run ./... — clean
  • Renderer unit test: guarded null default renders as ""
  • Compare-engine unit tests: empty-{}/null/trailing-newline → 0 diffs
  • Live home-ops: cilium keys restored as "", fleet before/after only those + checksum, no other app changed
  • Full home-ops live-parity sweep (pre-merge): cluster synced at/after #3229; confirm cilium 5 diffs → 0, ~700 empty-map false diffs gone, no new diffs

sholdee added 4 commits June 15, 2026 17:21
… false-diffs

Both fix sweep-only false diffs in the compare engine's loadFile, not drydock render:
- cleanupEmptyMetaMaps: drydock correctly emits argocd.argoproj.io/tracking-id (real
  Argo CD does too); the raw oracle lacks it; the ignore-rule strips it leaving an empty
  {} that falsely diffs against the oracle's absent map. ~700 false diffs.
- trimStringScalars: the oracle's yq re-serialization appends a trailing newline to
  block-scalar string values that drydock's faithful helm-Go-engine value lacks.
…ery resolves argocd/<name>

home-ops PR #3229 added explicit metadata.namespace: argocd to the apps/argocd
Application/ApplicationSet/AppProject manifests, so drydock default discovery resolves
apps as argocd/<name> without rendering the apps/argocd kustomization (which inflated the
argo-cd Helm chart on every run).
…Argo CD

Replace CoalesceValues (via ToRenderValuesWithSchemaValidation) with
MergeValues + ValidateAgainstSchema + inline top map. CoalesceValues
strips null chart defaults via cleanNilValues, causing hasKey guards
to evaluate false under drydock while helm v3 (Argo CD's bundled CLI)
retains them. Verified against helm v4.2.1 coalesce.go: the two paths
differ only in nil handling; subchart/global/schema coalescing is identical.
@sholdee

sholdee commented Jun 16, 2026

Copy link
Copy Markdown
Owner Author

✅ Full home-ops live-parity sweep — pre-merge gate PASS

Ran scripts/home-ops-live-parity.sh with the item-C binary against the live fleet (home-ops synced at #3229, kube 1.35.5 + 297 cluster api-versions). The --discover-kustomize-free script + default discovery resolved cleanly.

0 capture failures / 31 apps. Total diffs 795 (prior baseline) → 96:

item-C target result
empty annotations:{}/labels:{} 0 (compare cleanup)
annotations: null 0
cilium-config + checksum cascade 0 (helm fix — 3 keys restored as "")
cert-manager/velero trailing-newline 0 (trimStringScalars)

Remaining 96 = the known, accepted oracle-fidelity bucket (28 helm-hook resources the raw oracle includes but Argo CD + drydock exclude; 34 namespace-injection pairs where raw helm omits the namespace and drydock correctly stamps it). 0 in-place field diffs, 0 new diffs — the compare cleanup only removes false diffs and the helm fix only touched cilium (whole-fleet before/after confirmed). These 96 are inherent to the cache-free oracle (raw kustomize/helm vs Argo CD's post-processed output), not drydock render bugs.

Gate met: cilium 5 diffs → 0, ~700 empty-map false diffs retired, no regressions.

@sholdee sholdee merged commit 6c8f358 into main Jun 16, 2026
12 checks passed
@sholdee sholdee deleted the feat/item-c-serialization branch June 20, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant