Context
options.Merge combines a base BundleDeploymentOptions with per-target customization options. For several fields it appends the customization slice to the base slice without checking for duplicates:
DownstreamResources - both base and a target customization may reference the same (Kind, Name) resource. The current code appends unconditionally, causing the copy to run twice for the same source/destination pair.
Helm.ValuesFrom - a customization can re-list a ConfigMapKeyRef or SecretKeyRef that is already in the base, causing the same values to be applied twice.
Diff.ComparePatches - a customization can re-list a patch for the same (APIVersion, Kind, Namespace, Name) tuple. With the current append, both patches are applied; if they differ the outcome is non-obvious.
The duplicate-copy issue is already present for DownstreamResources in #5177 and will become more pronounced once multiple target customisations per target are supported (#4940), as each customisation layer that re-references the same resource will add another copy to the list.
Expected behavior
options.Merge deduplicates each of these slices so that a resource (or values source, or compare patch) referenced in both base and the customization appears only once in the result. For ComparePatches the customization entry should take precedence when both target the same resource identity (APIVersion, Kind, Namespace, Name).
Current behavior
Duplicate entries accumulate silently. For DownstreamResources this means redundant copy operations on every reconcile. For ValuesFrom the same Helm values file is loaded twice, potentially causing unexpected merging. For ComparePatches both the base and the customization patches are applied to the same resource.
Note
mergeComparePatches in internal/cmd/cli/bundlediff.go already implements dedup-with-precedence for ComparePatches; that logic (or a variation of it) could be reused or extracted into a shared helper used by options.Merge.
References
Context
options.Mergecombines a baseBundleDeploymentOptionswith per-target customization options. For several fields it appends the customization slice to the base slice without checking for duplicates:DownstreamResources- both base and a target customization may reference the same(Kind, Name)resource. The current code appends unconditionally, causing the copy to run twice for the same source/destination pair.Helm.ValuesFrom- a customization can re-list aConfigMapKeyReforSecretKeyRefthat is already in the base, causing the same values to be applied twice.Diff.ComparePatches- a customization can re-list a patch for the same(APIVersion, Kind, Namespace, Name)tuple. With the current append, both patches are applied; if they differ the outcome is non-obvious.The duplicate-copy issue is already present for
DownstreamResourcesin #5177 and will become more pronounced once multiple target customisations per target are supported (#4940), as each customisation layer that re-references the same resource will add another copy to the list.Expected behavior
options.Mergededuplicates each of these slices so that a resource (or values source, or compare patch) referenced in both base and the customization appears only once in the result. ForComparePatchesthe customization entry should take precedence when both target the same resource identity(APIVersion, Kind, Namespace, Name).Current behavior
Duplicate entries accumulate silently. For
DownstreamResourcesthis means redundant copy operations on every reconcile. ForValuesFromthe same Helm values file is loaded twice, potentially causing unexpected merging. ForComparePatchesboth the base and the customization patches are applied to the same resource.Note
mergeComparePatchesininternal/cmd/cli/bundlediff.goalready implements dedup-with-precedence forComparePatches; that logic (or a variation of it) could be reused or extracted into a shared helper used byoptions.Merge.References