fix(bundler): write recipe.yaml for every deployer, not just helm - #2759
Conversation
The recipe write was gated on the helm deployer, so argocd, argocd-helm, flux and helmfile bundles carried no recipe at all. ADR-021 and #2528 both build on the premise that every bundle embeds a deterministic recipe.yaml, which held for one deployer out of five. All five now write it through the same deterministic serializer, so the bytes are identical across deployers and the file lands in checksums.txt and therefore in the attestation subject. Fixes: #2753 Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
Recipe evidence checkNo leaf overlays affected by this PR. This gate is warning-only and never blocks merge. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (10)
Included review availability: Your plan provides up to 12 included reviews per hour; 10 remain after this review. 📝 WalkthroughWalkthroughThe bundler now writes the resolved Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to Every deployer bundle now consistently includes the resolved recipe with checksum and output inventory coverage. No actionable merge risk remains. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
🌿 Preview your docs: https://nvidia-preview-fix-2753-bundle-recipe.docs.buildwithfern.com/aicr |
Coverage Report ✅
Coverage BadgeMerging this branch will increase overall coverage
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. |
Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
Summary
Write the resolved
recipe.yamlat the bundle root for every deployer, not onlyhelm. Four of the five bundle formats carried no recipe at all.Motivation / Context
pkg/bundler/bundler.gogated the recipe write onb.Config.Deployer() == config.DeployerHelm, and that was its only write site, soargocd,argocd-helm,fluxandhelmfilebundles shipped without one.ADR-021 Decision 5 and #2528 both build on the premise that "every bundle embeds a deterministic
recipe.yaml, so the recipe and bundle forms share one code path." That premise is what makesupgrade-check --from <bundle>cheap, and it held for one deployer out of five: an operator on Argo CD or Flux had no recipe in their bundle to re-resolve.Fixes: #2753
Related: #2528, #2531, #2758
Type of Change
Component(s) Affected
cmd/aicr,pkg/cli)cmd/aicrd,pkg/server)pkg/recipe)pkg/bundler,pkg/component/*)pkg/collector,pkg/snapshotter)pkg/validator)pkg/errors,pkg/k8s)docs/,examples/)Implementation Notes
One serializer path, not one per deployer. The write moved out of the deployer conditional rather than being added to each deployer, so all five go through the same
serializer.MarshalYAMLDeterministiccall. Verified: the emittedrecipe.yamlis byte-identical across all five (same SHA256). This matters because the file feedschecksums.txt, which is the subject of the bundle attestation — re-marshaling per deployer would have made two bundles built from one recipe disagree on bytes while looking correct in a file listing.Checksums and attestation need no change. The write already happened before
checksum.WriteChecksums, so the new file lands in the manifest and the attestation subject automatically. Confirmedrecipe.yamlis present inchecksums.txtfor all five deployers.The new file is inert everywhere it could have been active:
kustomization.yamluses an explicitresources:list, so the recipe is never applied to a cluster.helm lintpasses,helm templaterenders unchanged, andhelm packageincludesrecipe.yamlin the tarball as a data file outsidetemplates/, so it never becomes a cluster object.checksums.txtalready rode along the same way, so this adds no new category of file to a published chart — and for OCI-published argocd-helm bundles it means the recipe travels with the artifact, which is what the--from <bundle>form needs.Layout gate.
requiredRootPathsinlayout_test.gonow listsrecipe.yamlfor all five deployers.TestBundleLayoutMatchesManifestonly fails on removals, treating additions as an un-refreshed manifest, so without this floor a future regression on the other four would have read as benign drift rather than a broken promise.Out of scope, filed separately. A bundle still does not record which deployer built it, which ADR-021 line 402 and #2528 both assert that it does. Split out as #2758, since it needs a new bundle-root surface and a naming decision rather than a gate removal.
Testing
go test -race ./pkg/bundler/... golangci-lint run -c .golangci.yaml ./pkg/bundler/... make lintBoth regression gates were verified to fail without the fix (change reverted, tests run, change restored):
TestMake_EveryDeployerEmitsRecipe(new) — fails on argocd, argocd-helm, flux, helmfile withno such file or directory.TestBundleLayoutMatchesManifest— fails on the same four with<deployer> no longer emits "recipe.yaml", which the frozen layout promises.The new test asserts per deployer that the file exists, parses back as a
RecipeResult, appears in the checksum inventory and in the reported result files, and that all five are byte-identical.Results:
go test -race ./pkg/bundler/passes;golangci-lintreports 0 issues.Coverage:
pkg/bundler: 86.8% → 86.8%(no change).Four failures in
pkg/bundler/attestation(×3) andpkg/bundler/validations(×1) are pre-existing and environmental — they need network egress my local sandbox blocks. Confirmed identical on unmodifiedmainbefore and after this change.make lintpasseslint-go(0 issues),lint-yaml,license,check-docs-filenames,check-docs-mdx,check-docs-mdx-parse,check-depproxy-kitandcheck-upgrade-records. Two targets could not execute locally for sandbox reasons unrelated to this diff:check-agents-sync(the tool usesdiff <(…) <(…); verified by hand thatAGENTS.mdmatches.claude/CLAUDE.mdfrom line 5) andbom-pinning-check(macOSmktempdenial, and this PR touches no chart, recipe or registry file). CI covers both.Risk Assessment
Rollout notes: Purely additive to the bundle tree — one new root file on four deployers, none removed or renamed, so no integrator path breaks. Bundle bytes change for those four (a new file plus its
checksums.txtentry), so any pinned bundle digest for argocd, argocd-helm, flux or helmfile shifts once. Helm bundles are unchanged.Checklist
make testwith-race)make lint)git commit -S)