fix(recipe): reject unapplied ComponentRef.Patches; fix coherence godoc#1589
fix(recipe): reject unapplied ComponentRef.Patches; fix coherence godoc#1589yuanchen8911 wants to merge 1 commit into
Conversation
|
🌿 Preview your docs: https://nvidia-preview-fix-1588-followups.docs.buildwithfern.com/aicr |
Recipe evidence checkNo leaf overlays affected by this PR. This gate is warning-only and never blocks merge. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR normalizes Estimated code review effort: 4 (Complex) | ~75 minutes Possibly related issues
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@api/aicr/v1/server.yaml`:
- Around line 1464-1498: The componentRefs schema description still mentions
deployment order even though order was removed from componentRefs[]. Update the
description in the server.yaml schema block so it no longer implies ordering and
instead points readers to deploymentOrder for sequencing. Use the componentRefs
and deploymentOrder schema descriptions as the places to adjust the wording.
- Around line 1464-1497: The `RecipeResponse` schema in `server.yaml` documents
Helm/Kustomize fields but does not state that `patches` is unsupported, so
update the OpenAPI contract to explicitly reject or forbid `patches` on this
request body. Add the unsupported-field note in the `properties`/validation text
near the existing `type`, `tag`, `source`, and `path` descriptions so
`/v1/bundle` consumers know `patches` is not accepted and will fail loudly.
In `@docs/user/cli-reference.md`:
- Around line 493-498: The normalized Helm example in the CLI reference is
missing the chart field, so the example shape is incomplete. Update the
`componentRefs` Helm entry shown alongside `deploymentOrder` to include `chart`
as well as the existing `type`, `version`, and `source`, matching the normalized
Helm format used by the API examples and the `componentRefs` documentation.
In `@pkg/client/v1/aicr_internal_test.go`:
- Around line 1124-1133: The blocking provider in
blockingReadFileProvider.ReadFile can wait forever on readUnblock and currently
ignores context cancellation. Update ReadFile to watch ctx.Done() while waiting,
and if the context is canceled return ctx.Err() instead of continuing to block.
Keep the readStarted signaling behavior intact, but ensure the wait path in
ReadFile respects the DataProvider contract and exits promptly on cancellation.
- Around line 1055-1112: Refactor TestAdoptRecipe_RejectsIncoherentRef into a
table-driven test because it exercises three distinct adoptRecipe scenarios.
Keep the shared setup in TestAdoptRecipe_RejectsIncoherentRef and move the
incoherent Helm+tag rejection, the lowercase type canonicalization, and the
type-less registry back-fill checks into table cases. Use the same
client.adoptRecipe and a base helper, but make per-case expected error/result
assertions data-driven so adding new coherence cases stays consistent.
In `@pkg/recipe/componentref_coherence_test.go`:
- Around line 124-165: Refactor TestRecipeResultValidateCoherence and the other
multi-scenario coherence test into table-driven tests using a tests :=
[]struct{...} loop with subtests, so each scenario (coherent, incoherent,
disabled, nil receiver) is defined declaratively and checked per case. Keep the
existing assertions for expected error presence, ErrCodeInvalidRequest matching,
and required substrings, but move them into per-case fields and a shared loop;
use the existing RecipeResult.ValidateCoherence and ComponentRef symbols to
locate the logic.
In `@pkg/recipe/metadata.go`:
- Around line 98-101: Tighten the godoc for the Patches field in metadata.go so
it reflects current behavior: note that ValidateCoherence only skips disabled
refs, so the comment should say “enabled ref” instead of implying all refs are
checked. Also clarify the Flux behavior wording so it does not say Flux “never
sees” these refs; it should state that Flux may still receive coherent external
Kustomize refs and reject them by Type. Use the Patches and ValidateCoherence
symbols to update the surrounding comment blocks consistently.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 3bdfc9aa-d4ec-40bd-9cce-b6dcc09ef464
📒 Files selected for processing (11)
api/aicr/v1/server.yamldocs/user/cli-reference.mdpkg/bundler/bundler.gopkg/bundler/bundler_test.gopkg/client/v1/aicr_internal_test.gopkg/client/v1/bundle.gopkg/recipe/componentref_coherence_test.gopkg/recipe/loader.gopkg/recipe/metadata.gopkg/recipe/metadata_store.gopkg/server/bundle_handler_test.go
32bd86c to
0d75f25
Compare
0d75f25 to
1f1b61e
Compare
mchmarny
left a comment
There was a problem hiding this comment.
Clean, tightly-scoped follow-up to #1585. Verified against the head branch: the patches check fails closed first in coherenceProblem(), ValidateCoherence skips disabled refs as claimed, the new test cases cover both Helm+patches and Kustomize+patches, and no in-tree recipe sets patches so nothing regresses — the low-risk assessment holds. godoc/OpenAPI/doc accuracy improvements all check out.
One nit inline on the 400 message wording; nothing blocks the substance.
Two non-code items to note:
- CI:
Tier 1: eks-training (argocd-oci)failed at "Run KWOK test" while every other Tier 1 combo (including otherargocd-ocirecipes) passed. No recipe usespatchesand the only logic change here is the patches rejection, so this isn't attributable to the diff — looks like a flake (the Actions jobs API was also 502-ing). Worth a re-run to confirm green. - Rebase:
needs-rebase/ stacked on #1585 — can't merge until that lands, as the PR notes.
| // no patches field). Fail closed on any type rather than drop it silently. | ||
| if len(ref.Patches) > 0 { | ||
| return fmt.Sprintf("component %q declares patches, but no deployer applies patch files; "+ | ||
| "remove `patches` (it would be silently dropped). See #1588.", ref.Name) |
There was a problem hiding this comment.
nit: the parenthetical (it would be silently dropped) reads as contradictory in a user-facing 400 — the whole point of this change is that the ref is now rejected, not dropped. Suggest stating why removal is safe instead: e.g. "remove \patches` (it is never applied by any deployer). See #1588."`
There was a problem hiding this comment.
Good catch — the parenthetical predated the fail-closed behavior and read as contradictory. Reworded in 19da720 to state why removal is safe: "remove patches (removing it does not change the generated bundle). See #1588." Kept the leading clause ("no deployer applies patch files") as the reason, so the parenthetical now carries the safety statement rather than repeating it.
On the two non-code notes: the branch is rebased onto main with #1585 merged, and the force-push re-runs the full Tier 1 matrix, which covers the flaky eks-training (argocd-oci) KWOK job.
One heads-up from the local qualify run: make scan now fails on GHSA-fxhp-mv3v-67qp (oras.land/oras-go/v2 <= 2.6.1, published 2026-07-01, no patched release yet). Pre-existing on main — this PR touches no dependencies.
…oc (NVIDIA#1588) Follow-ups surfaced by the cross-review of NVIDIA#1585. ComponentRef.Patches is carried through resolution (deep-copied, overlay- merged) but applied by NO deployer — localformat's Component has no patches field and every generator omits it — so a recipe that declares `patches:` silently produces an unpatched bundle. Reject any ref that declares patches in coherenceProblem (fail loud) rather than dropping them silently, and mark the field's godoc as unapplied. No recipe uses `patches` in-tree or in the internal recipes repo, so this only turns a latent silent-drop into a clear error; implementing patch application (or removing the field) is the alternative, tracked in NVIDIA#1588. Also correct the coherenceProblem godoc: it over-generalized that "the deployers do not trust the declared Type." That holds for the field-classifying deployers (localformat and the Helm/Helmfile/ArgoCD generators built on it), but the Flux generator is Helm-only and switches on Type (it already rejects a non-Helm ref with a clear error). Clarify this. Fixes: NVIDIA#1588 Related: NVIDIA#1585 Document the rejected field for authors: add patches to the OpenAPI componentRefs schema (marked unsupported/rejected) and a note in docs/integrator/recipe-development.md, and clarify the Go field comment that only ENABLED refs are rejected (disabled are skipped). Also finish the type-handling wording: the godoc and the Helm-ref error no longer over-claim that all deployers classify by tag/path — the field-classifying deployers do (building a mismatched Helm ref as Kustomize), while the Flux deployer switches on canonical Type and rejects a non-Helm ref outright. Review nits: correct the componentRefs schema description (order is the top-level deploymentOrder, not per-ref), add chart to the cli-reference Helm example for parity with the API examples, and make the blocking test DataProvider honor context cancellation. Declare the top-level deploymentOrder property in the RecipeResponse schema (array of component names) and include it in the /v1/bundle example, so a GET->POST round trip through a generated client preserves deployment sequencing instead of dropping it. Correct the remaining Flux wording: a Helm ref carrying tag/path builds as Kustomize under the field-classifying deployers but as Helm under Flux (which switches on the declared Type) — it is not rejected by Flux; only an explicitly non-Helm type is. Fixed in the godoc bullet, the Helm-ref error, and the case-insensitive/default-branch comments. Signed-off-by: Yuan Chen <yuanchen97@gmail.com>
1f1b61e to
19da720
Compare
Summary
Address the follow-ups surfaced by the cross-review of #1585: reject the inert
ComponentRef.Patchesfield (fail loud instead of silently dropping requested patches), correct thecoherenceProblemtype-handling wording (localformat vs Flux), and tighten the OpenAPIcomponentRefscontract that the same review exposed.Motivation / Context
ComponentRef.Patchesis never applied. The field ("patch files for Kustomize") is carried through resolution — deep-copied, overlay-merged — but no deployer applies it (localformat.Componenthas no patches field; every generator omits it). So a recipe/overlay that setspatches:silently produces an unpatched bundle. No recipe uses it in-tree or in the internalnkx-recipesrepo, so it is purely latent.coherenceProblemgodoc over-generalized how deployers treatType. The field-classifying deployers (localformat + Helm/Helmfile/ArgoCD) key offtag/path; the Flux generator switches on the declaredType(Helm-only). So aType: Helmref carryingtag/pathbuilds as Kustomize under the field-classifiers but as Helm under Flux — the same ref deploys differently.componentRefsinaccuracies the review turned up:patcheswas undocumented, the top-leveldeploymentOrder(which the server serializes andPOST /v1/bundleaccepts) was never declared, and the description implied a per-ref order.Fixes: #1588
Related: #1585
Type of Change
Component(s) Affected
pkg/recipe)api/aicr/v1/server.yaml)docs/integrator/recipe-development.md,docs/user/cli-reference.md)Implementation Notes
coherenceProblemrejects any ref that declarespatches(all types — no deployer applies them), before the type checks;ValidateCoherencestill skips disabled refs.ComponentRef.Patchesgodoc marked NOT-APPLIED (enabled refs rejected; disabled skipped). Implementing application or removing the field is the alternative, tracked in Follow-ups from #1585: unapplied ComponentRef.Patches, Flux+Kustomize gap, coherence godoc #1588.api/aicr/v1/server.yaml): documentedpatchesas unsupported/rejected; declared the top-leveldeploymentOrder(array<string>) property with a note to preserve it on a GET→POST round trip; corrected thecomponentRefsdescription (order is top-level, not per-ref); addeddeploymentOrderto the/v1/bundleexample.recipe-development.mdnotespatchesis unsupported/rejected;cli-reference.mdexample gainschartfor parity with the API examples.flux.godefault → "unsupported component type"); captured in the godoc.DataProvidernow honors context cancellation (returnsctx.Err()instead of parking).Testing
Adds coherence test cases (Helm+patches and Kustomize+patches both rejected).
Risk Assessment
nkx-recipes) and no deployer applies; turns a latent silent-drop into a clearErrCodeInvalidRequest. Remaining changes are docs/OpenAPI accuracy + a test-only fix. Trivially reversible.Rollout notes: if patches are ever needed, implement application (or drop the field) per #1588 rather than relying on the previous silent no-op.
Checklist
make testwith-race)make lint)git commit -S)