From 3a018404ba3017127fe0219a61f58be0f1f6baa1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:36:34 +0000 Subject: [PATCH 1/7] Initial plan From 5aa05e8c23abb323480e5742629e02e8a1bce98c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:51:32 +0000 Subject: [PATCH 2/7] Add GetPluginKeyForConfig helper and update plugins to use dynamic keys Co-authored-by: camilamacedo86 <7708031+camilamacedo86@users.noreply.github.com> --- pkg/plugin/helpers.go | 53 ++++++++++++++ pkg/plugin/helpers_test.go | 73 +++++++++++++++++++ .../golang/deploy-image/v1alpha1/api.go | 8 +- .../golang/deploy-image/v1alpha1/plugin.go | 1 - .../optional/autoupdate/v1alpha/edit.go | 2 +- .../optional/autoupdate/v1alpha/init.go | 2 +- .../optional/autoupdate/v1alpha/plugin.go | 8 +- .../optional/grafana/v1alpha/commons.go | 8 +- pkg/plugins/optional/grafana/v1alpha/edit.go | 2 +- pkg/plugins/optional/grafana/v1alpha/init.go | 2 +- .../optional/grafana/v1alpha/plugin.go | 1 - pkg/plugins/optional/helm/v1alpha/commons.go | 8 +- pkg/plugins/optional/helm/v1alpha/plugin.go | 1 - pkg/plugins/optional/helm/v2alpha/edit.go | 8 +- pkg/plugins/optional/helm/v2alpha/plugin.go | 1 - 15 files changed, 159 insertions(+), 19 deletions(-) diff --git a/pkg/plugin/helpers.go b/pkg/plugin/helpers.go index 304bd1e4637..24552350a8c 100644 --- a/pkg/plugin/helpers.go +++ b/pkg/plugin/helpers.go @@ -40,6 +40,59 @@ func SplitKey(key string) (string, string) { return keyParts[0], keyParts[1] } +// GetPluginKeyForConfig searches for a plugin key in the plugin chain that should be used for storing +// plugin configuration. When a plugin is wrapped in a bundle with a custom name, the bundle's key will +// be in the plugin chain instead of the plugin's own key. +// +// The function first tries to find the plugin's own key (via KeyFor). If not found, it looks for a key +// with a matching name prefix (before the domain) and version. This handles the case where a plugin like +// "deploy-image.go.kubebuilder.io/v1-alpha" is wrapped in a bundle named "deploy-image.my-domain/v1-alpha". +// +// If no match is found in the plugin chain, it falls back to using the plugin's own key. +func GetPluginKeyForConfig(pluginChain []string, p Plugin) string { + pluginKey := KeyFor(p) + + // First, try exact match + for _, key := range pluginChain { + if key == pluginKey { + return pluginKey + } + } + + // If no exact match, look for a key with matching base name and version + // This handles custom bundles that wrap the plugin + pluginName, _ := SplitKey(pluginKey) + pluginVersion := p.Version().String() + + // Extract the base name (part before the domain) + // E.g., "deploy-image.go.kubebuilder.io" -> "deploy-image" + baseName := pluginName + if idx := strings.Index(pluginName, "."); idx != -1 { + baseName = pluginName[:idx] + } + + for _, key := range pluginChain { + name, version := SplitKey(key) + if version != pluginVersion { + continue + } + + // Check if this key has the same base name + // E.g., "deploy-image.my-domain" has base name "deploy-image" + keyBaseName := name + if idx := strings.Index(name, "."); idx != -1 { + keyBaseName = name[:idx] + } + + if keyBaseName == baseName { + return key + } + } + + // Fall back to the plugin's own key if no match found + return pluginKey +} + // Validate ensures a Plugin is valid. func Validate(p Plugin) error { if err := validateName(p.Name()); err != nil { diff --git a/pkg/plugin/helpers_test.go b/pkg/plugin/helpers_test.go index 557a9f04871..db51f3d8c37 100644 --- a/pkg/plugin/helpers_test.go +++ b/pkg/plugin/helpers_test.go @@ -185,3 +185,76 @@ var _ = Describe("CommonSupportedProjectVersions", func() { } }) }) + +var _ = Describe("GetPluginKeyForConfig", func() { + It("should return the plugin's own key when it's in the plugin chain", func() { + plugin := mockPlugin{ + name: "deploy-image.go.kubebuilder.io", + version: Version{Number: 1, Stage: stage.Alpha}, + } + pluginChain := []string{ + "go.kubebuilder.io/v4", + "deploy-image.go.kubebuilder.io/v1-alpha", + } + Expect(GetPluginKeyForConfig(pluginChain, plugin)).To(Equal("deploy-image.go.kubebuilder.io/v1-alpha")) + }) + + It("should return the bundle key when plugin is wrapped in a bundle", func() { + plugin := mockPlugin{ + name: "deploy-image.go.kubebuilder.io", + version: Version{Number: 1, Stage: stage.Alpha}, + } + pluginChain := []string{ + "go.kubebuilder.io/v4", + "deploy-image.my-domain/v1-alpha", + } + Expect(GetPluginKeyForConfig(pluginChain, plugin)).To(Equal("deploy-image.my-domain/v1-alpha")) + }) + + It("should fallback to plugin's own key when no match in chain", func() { + plugin := mockPlugin{ + name: "deploy-image.go.kubebuilder.io", + version: Version{Number: 1, Stage: stage.Alpha}, + } + pluginChain := []string{ + "go.kubebuilder.io/v4", + } + Expect(GetPluginKeyForConfig(pluginChain, plugin)).To(Equal("deploy-image.go.kubebuilder.io/v1-alpha")) + }) + + It("should match on base name and version", func() { + plugin := mockPlugin{ + name: "deploy-image.go.kubebuilder.io", + version: Version{Number: 1, Stage: stage.Alpha}, + } + pluginChain := []string{ + "go.kubebuilder.io/v4", + "deploy-image.operator-sdk.io/v1-alpha", + } + Expect(GetPluginKeyForConfig(pluginChain, plugin)).To(Equal("deploy-image.operator-sdk.io/v1-alpha")) + }) + + It("should not match if version differs", func() { + plugin := mockPlugin{ + name: "deploy-image.go.kubebuilder.io", + version: Version{Number: 1, Stage: stage.Alpha}, + } + pluginChain := []string{ + "go.kubebuilder.io/v4", + "deploy-image.my-domain/v2-alpha", + } + Expect(GetPluginKeyForConfig(pluginChain, plugin)).To(Equal("deploy-image.go.kubebuilder.io/v1-alpha")) + }) + + It("should not match if base name differs", func() { + plugin := mockPlugin{ + name: "deploy-image.go.kubebuilder.io", + version: Version{Number: 1, Stage: stage.Alpha}, + } + pluginChain := []string{ + "go.kubebuilder.io/v4", + "other-plugin.my-domain/v1-alpha", + } + Expect(GetPluginKeyForConfig(pluginChain, plugin)).To(Equal("deploy-image.go.kubebuilder.io/v1-alpha")) + }) +}) diff --git a/pkg/plugins/golang/deploy-image/v1alpha1/api.go b/pkg/plugins/golang/deploy-image/v1alpha1/api.go index 18798f7ba53..ce6fcdb0875 100644 --- a/pkg/plugins/golang/deploy-image/v1alpha1/api.go +++ b/pkg/plugins/golang/deploy-image/v1alpha1/api.go @@ -190,8 +190,12 @@ func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error { } // Track the resources following a declarative approach + // Get the correct plugin key from the plugin chain - this handles the case where + // this plugin is wrapped in a bundle with a custom name (e.g., in operator-sdk) + key := plugin.GetPluginKeyForConfig(p.config.GetPluginChain(), Plugin{}) + cfg := PluginConfig{} - if err = p.config.DecodePluginConfig(pluginKey, &cfg); errors.As(err, &config.UnsupportedFieldError{}) { + if err = p.config.DecodePluginConfig(key, &cfg); errors.As(err, &config.UnsupportedFieldError{}) { // Skip tracking as the config doesn't support per-plugin configuration return nil } else if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) { @@ -213,7 +217,7 @@ func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error { Options: configDataOptions, }) - if err = p.config.EncodePluginConfig(pluginKey, cfg); err != nil { + if err = p.config.EncodePluginConfig(key, cfg); err != nil { return fmt.Errorf("error encoding plugin configuration: %w", err) } diff --git a/pkg/plugins/golang/deploy-image/v1alpha1/plugin.go b/pkg/plugins/golang/deploy-image/v1alpha1/plugin.go index 4608e0dec79..7fe88f8449e 100644 --- a/pkg/plugins/golang/deploy-image/v1alpha1/plugin.go +++ b/pkg/plugins/golang/deploy-image/v1alpha1/plugin.go @@ -29,7 +29,6 @@ const pluginName = "deploy-image." + golang.DefaultNameQualifier var ( pluginVersion = plugin.Version{Number: 1, Stage: stage.Alpha} supportedProjectVersions = []config.Version{cfgv3.Version} - pluginKey = plugin.KeyFor(Plugin{}) ) var _ plugin.CreateAPI = Plugin{} diff --git a/pkg/plugins/optional/autoupdate/v1alpha/edit.go b/pkg/plugins/optional/autoupdate/v1alpha/edit.go index 0f82926d40c..bfaa05d5bec 100644 --- a/pkg/plugins/optional/autoupdate/v1alpha/edit.go +++ b/pkg/plugins/optional/autoupdate/v1alpha/edit.go @@ -36,7 +36,7 @@ func (p *editSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta * subcmdMeta.Examples = fmt.Sprintf(` # Edit a common project with this plugin %[1]s edit --plugins=%[2]s -`, cliMeta.CommandName, pluginKey) +`, cliMeta.CommandName, plugin.KeyFor(Plugin{})) } func (p *editSubcommand) InjectConfig(c config.Config) error { diff --git a/pkg/plugins/optional/autoupdate/v1alpha/init.go b/pkg/plugins/optional/autoupdate/v1alpha/init.go index 633054040e6..1bc04ad0804 100644 --- a/pkg/plugins/optional/autoupdate/v1alpha/init.go +++ b/pkg/plugins/optional/autoupdate/v1alpha/init.go @@ -36,7 +36,7 @@ func (p *initSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta * subcmdMeta.Examples = fmt.Sprintf(` # Initialize a common project with this plugin %[1]s init --plugins=%[2]s -`, cliMeta.CommandName, pluginKey) +`, cliMeta.CommandName, plugin.KeyFor(Plugin{})) } func (p *initSubcommand) InjectConfig(c config.Config) error { diff --git a/pkg/plugins/optional/autoupdate/v1alpha/plugin.go b/pkg/plugins/optional/autoupdate/v1alpha/plugin.go index 8857c025408..f34f2e41c21 100644 --- a/pkg/plugins/optional/autoupdate/v1alpha/plugin.go +++ b/pkg/plugins/optional/autoupdate/v1alpha/plugin.go @@ -46,7 +46,6 @@ const pluginName = "autoupdate." + plugins.DefaultNameQualifier var ( pluginVersion = plugin.Version{Number: 1, Stage: stage.Alpha} supportedProjectVersions = []config.Version{cfgv3.Version} - pluginKey = plugin.KeyFor(Plugin{}) ) // Plugin implements the plugin.Full interface @@ -81,13 +80,16 @@ func (p Plugin) DeprecationWarning() string { // insertPluginMetaToConfig will insert the metadata to the plugin configuration func insertPluginMetaToConfig(target config.Config, cfg pluginConfig) error { - err := target.DecodePluginConfig(pluginKey, cfg) + // Get the correct plugin key from the plugin chain + key := plugin.GetPluginKeyForConfig(target.GetPluginChain(), Plugin{}) + + err := target.DecodePluginConfig(key, cfg) if !errors.As(err, &config.UnsupportedFieldError{}) { if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) { return fmt.Errorf("error decoding plugin configuration: %w", err) } - if err = target.EncodePluginConfig(pluginKey, cfg); err != nil { + if err = target.EncodePluginConfig(key, cfg); err != nil { return fmt.Errorf("error encoding plugin configuration: %w", err) } } diff --git a/pkg/plugins/optional/grafana/v1alpha/commons.go b/pkg/plugins/optional/grafana/v1alpha/commons.go index 3cd97b507cd..576c77ce474 100644 --- a/pkg/plugins/optional/grafana/v1alpha/commons.go +++ b/pkg/plugins/optional/grafana/v1alpha/commons.go @@ -21,17 +21,21 @@ import ( "fmt" "sigs.k8s.io/kubebuilder/v4/pkg/config" + "sigs.k8s.io/kubebuilder/v4/pkg/plugin" ) // InsertPluginMetaToConfig will insert the metadata to the plugin configuration func InsertPluginMetaToConfig(target config.Config, cfg pluginConfig) error { - err := target.DecodePluginConfig(pluginKey, cfg) + // Get the correct plugin key from the plugin chain + key := plugin.GetPluginKeyForConfig(target.GetPluginChain(), Plugin{}) + + err := target.DecodePluginConfig(key, cfg) if !errors.As(err, &config.UnsupportedFieldError{}) { if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) { return fmt.Errorf("error decoding plugin configuration: %w", err) } - if err = target.EncodePluginConfig(pluginKey, cfg); err != nil { + if err = target.EncodePluginConfig(key, cfg); err != nil { return fmt.Errorf("error encoding plugin configuration: %w", err) } } diff --git a/pkg/plugins/optional/grafana/v1alpha/edit.go b/pkg/plugins/optional/grafana/v1alpha/edit.go index c688c188b83..90c4180efb1 100644 --- a/pkg/plugins/optional/grafana/v1alpha/edit.go +++ b/pkg/plugins/optional/grafana/v1alpha/edit.go @@ -37,7 +37,7 @@ func (p *editSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta * subcmdMeta.Examples = fmt.Sprintf(` # Edit a common project with this plugin %[1]s edit --plugins=%[2]s -`, cliMeta.CommandName, pluginKey) +`, cliMeta.CommandName, plugin.KeyFor(Plugin{})) } func (p *editSubcommand) InjectConfig(c config.Config) error { diff --git a/pkg/plugins/optional/grafana/v1alpha/init.go b/pkg/plugins/optional/grafana/v1alpha/init.go index a5abdc0197d..fa400fdf8f0 100644 --- a/pkg/plugins/optional/grafana/v1alpha/init.go +++ b/pkg/plugins/optional/grafana/v1alpha/init.go @@ -37,7 +37,7 @@ func (p *initSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta * subcmdMeta.Examples = fmt.Sprintf(` # Initialize a common project with this plugin %[1]s init --plugins=%[2]s -`, cliMeta.CommandName, pluginKey) +`, cliMeta.CommandName, plugin.KeyFor(Plugin{})) } func (p *initSubcommand) InjectConfig(c config.Config) error { diff --git a/pkg/plugins/optional/grafana/v1alpha/plugin.go b/pkg/plugins/optional/grafana/v1alpha/plugin.go index 39e77079cfd..7c56ea5fb57 100644 --- a/pkg/plugins/optional/grafana/v1alpha/plugin.go +++ b/pkg/plugins/optional/grafana/v1alpha/plugin.go @@ -29,7 +29,6 @@ const pluginName = "grafana." + plugins.DefaultNameQualifier var ( pluginVersion = plugin.Version{Number: 1, Stage: stage.Alpha} supportedProjectVersions = []config.Version{cfgv3.Version} - pluginKey = plugin.KeyFor(Plugin{}) ) // Plugin implements the plugin.Full interface diff --git a/pkg/plugins/optional/helm/v1alpha/commons.go b/pkg/plugins/optional/helm/v1alpha/commons.go index 02370c48dae..e15b634bea0 100644 --- a/pkg/plugins/optional/helm/v1alpha/commons.go +++ b/pkg/plugins/optional/helm/v1alpha/commons.go @@ -21,15 +21,19 @@ import ( "fmt" "sigs.k8s.io/kubebuilder/v4/pkg/config" + "sigs.k8s.io/kubebuilder/v4/pkg/plugin" ) func insertPluginMetaToConfig(target config.Config, cfg pluginConfig) error { - err := target.DecodePluginConfig(pluginKey, cfg) + // Get the correct plugin key from the plugin chain + key := plugin.GetPluginKeyForConfig(target.GetPluginChain(), Plugin{}) + + err := target.DecodePluginConfig(key, cfg) if !errors.As(err, &config.UnsupportedFieldError{}) { if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) { return fmt.Errorf("error decoding plugin configuration: %w", err) } - if err = target.EncodePluginConfig(pluginKey, cfg); err != nil { + if err = target.EncodePluginConfig(key, cfg); err != nil { return fmt.Errorf("error encoding plugin config: %w", err) } } diff --git a/pkg/plugins/optional/helm/v1alpha/plugin.go b/pkg/plugins/optional/helm/v1alpha/plugin.go index 231a15860c1..26ea303e1e6 100644 --- a/pkg/plugins/optional/helm/v1alpha/plugin.go +++ b/pkg/plugins/optional/helm/v1alpha/plugin.go @@ -29,7 +29,6 @@ const pluginName = "helm." + plugins.DefaultNameQualifier var ( pluginVersion = plugin.Version{Number: 1, Stage: stage.Alpha} supportedProjectVersions = []config.Version{cfgv3.Version} - pluginKey = plugin.KeyFor(Plugin{}) ) // Plugin implements the plugin.Full interface diff --git a/pkg/plugins/optional/helm/v2alpha/edit.go b/pkg/plugins/optional/helm/v2alpha/edit.go index 87d9e1b778e..b31309d9b78 100644 --- a/pkg/plugins/optional/helm/v2alpha/edit.go +++ b/pkg/plugins/optional/helm/v2alpha/edit.go @@ -122,8 +122,12 @@ func (p *editSubcommand) Scaffold(fs machinery.Filesystem) error { } // Track the plugin configuration following a declarative approach + // Get the correct plugin key from the plugin chain - this handles the case where + // this plugin is wrapped in a bundle with a custom name + key := plugin.GetPluginKeyForConfig(p.config.GetPluginChain(), Plugin{}) + cfg := pluginConfig{} - if err = p.config.DecodePluginConfig(pluginKey, &cfg); errors.As(err, &config.UnsupportedFieldError{}) { + if err = p.config.DecodePluginConfig(key, &cfg); errors.As(err, &config.UnsupportedFieldError{}) { // Skip tracking as the config doesn't support per-plugin configuration return nil } else if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) { @@ -135,7 +139,7 @@ func (p *editSubcommand) Scaffold(fs machinery.Filesystem) error { cfg.ManifestsFile = p.manifestsFile cfg.OutputDir = p.outputDir - if err = p.config.EncodePluginConfig(pluginKey, cfg); err != nil { + if err = p.config.EncodePluginConfig(key, cfg); err != nil { return fmt.Errorf("error encoding plugin configuration: %w", err) } diff --git a/pkg/plugins/optional/helm/v2alpha/plugin.go b/pkg/plugins/optional/helm/v2alpha/plugin.go index 3f5fd9e2e25..855d4722813 100644 --- a/pkg/plugins/optional/helm/v2alpha/plugin.go +++ b/pkg/plugins/optional/helm/v2alpha/plugin.go @@ -29,7 +29,6 @@ const pluginName = "helm." + plugins.DefaultNameQualifier var ( pluginVersion = plugin.Version{Number: 2, Stage: stage.Alpha} supportedProjectVersions = []config.Version{cfgv3.Version} - pluginKey = plugin.KeyFor(Plugin{}) ) // Plugin implements the plugin.Full interface From d339af1f79f8207ecdeee08b436a86baed7027cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:55:36 +0000 Subject: [PATCH 3/7] Add integration test for plugin key resolution with bundles Co-authored-by: camilamacedo86 <7708031+camilamacedo86@users.noreply.github.com> --- .../deploy-image/v1alpha1/plugin_test.go | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go diff --git a/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go b/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go new file mode 100644 index 00000000000..ecda1179c6c --- /dev/null +++ b/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go @@ -0,0 +1,83 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "testing" + + "sigs.k8s.io/kubebuilder/v4/pkg/plugin" +) + +// TestGetPluginKeyForConfigIntegration tests that the plugin correctly resolves +// its key based on the plugin chain, supporting custom bundle names. +func TestGetPluginKeyForConfigIntegration(t *testing.T) { + p := Plugin{} + + tests := []struct { + name string + pluginChain []string + expected string + description string + }{ + { + name: "exact match", + pluginChain: []string{"go.kubebuilder.io/v4", "deploy-image.go.kubebuilder.io/v1-alpha"}, + expected: "deploy-image.go.kubebuilder.io/v1-alpha", + description: "When plugin is used directly, it should use its own key", + }, + { + name: "bundle match with custom domain", + pluginChain: []string{"go.kubebuilder.io/v4", "deploy-image.custom-domain/v1-alpha"}, + expected: "deploy-image.custom-domain/v1-alpha", + description: "When plugin is wrapped in bundle with custom domain, it should use bundle's key", + }, + { + name: "bundle match with operator-sdk domain", + pluginChain: []string{"go.kubebuilder.io/v4", "deploy-image.operator-sdk.io/v1-alpha"}, + expected: "deploy-image.operator-sdk.io/v1-alpha", + description: "When plugin is wrapped in operator-sdk bundle, it should use bundle's key", + }, + { + name: "no match - fallback to plugin key", + pluginChain: []string{"go.kubebuilder.io/v4"}, + expected: "deploy-image.go.kubebuilder.io/v1-alpha", + description: "When no matching key in chain, fallback to plugin's own key", + }, + { + name: "version mismatch - fallback", + pluginChain: []string{"go.kubebuilder.io/v4", "deploy-image.custom-domain/v2-alpha"}, + expected: "deploy-image.go.kubebuilder.io/v1-alpha", + description: "When version doesn't match, fallback to plugin's own key", + }, + { + name: "base name mismatch - fallback", + pluginChain: []string{"go.kubebuilder.io/v4", "other-plugin.custom-domain/v1-alpha"}, + expected: "deploy-image.go.kubebuilder.io/v1-alpha", + description: "When base name doesn't match, fallback to plugin's own key", + }, + } + + for _, tt := range tests { + tt := tt // capture range variable + t.Run(tt.name, func(t *testing.T) { + result := plugin.GetPluginKeyForConfig(tt.pluginChain, p) + if result != tt.expected { + t.Errorf("%s: Expected key %q, got %q", tt.description, tt.expected, result) + } + }) + } +} From 8b73bbdd7f77ae2e2eb0f9343b12a20396f75490 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:57:32 +0000 Subject: [PATCH 4/7] Update alpha generate and helm v1alpha to use dynamic plugin keys Co-authored-by: camilamacedo86 <7708031+camilamacedo86@users.noreply.github.com> --- pkg/cli/alpha/internal/generate.go | 4 +++- pkg/plugins/optional/helm/v1alpha/scaffolds/edit.go | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/cli/alpha/internal/generate.go b/pkg/cli/alpha/internal/generate.go index f6be341bbee..2276bf7c65f 100644 --- a/pkg/cli/alpha/internal/generate.go +++ b/pkg/cli/alpha/internal/generate.go @@ -279,7 +279,9 @@ func migrateAutoUpdatePlugin(s store.Store) error { // Migrates the Deploy Image plugin. func migrateDeployImagePlugin(s store.Store) error { var deployImagePlugin deployimagev1alpha1.PluginConfig - err := s.Config().DecodePluginConfig(plugin.KeyFor(deployimagev1alpha1.Plugin{}), &deployImagePlugin) + // Use GetPluginKeyForConfig to support custom bundle names + key := plugin.GetPluginKeyForConfig(s.Config().GetPluginChain(), deployimagev1alpha1.Plugin{}) + err := s.Config().DecodePluginConfig(key, &deployImagePlugin) if errors.As(err, &config.PluginKeyNotFoundError{}) { slog.Info("Deploy-image plugin not found, skipping migration") return nil diff --git a/pkg/plugins/optional/helm/v1alpha/scaffolds/edit.go b/pkg/plugins/optional/helm/v1alpha/scaffolds/edit.go index 0c2b35d3d0e..5a8ac07e506 100644 --- a/pkg/plugins/optional/helm/v1alpha/scaffolds/edit.go +++ b/pkg/plugins/optional/helm/v1alpha/scaffolds/edit.go @@ -141,7 +141,9 @@ func (s *editScaffolder) getDeployImagesEnvVars() map[string]string { } `json:"resources"` }{} - err := s.config.DecodePluginConfig(plugin.KeyFor(deployimagev1alpha1.Plugin{}), &pluginConfig) + // Use GetPluginKeyForConfig to support custom bundle names + key := plugin.GetPluginKeyForConfig(s.config.GetPluginChain(), deployimagev1alpha1.Plugin{}) + err := s.config.DecodePluginConfig(key, &pluginConfig) if err == nil { for _, res := range pluginConfig.Resources { image, ok := res.Options["image"] From 599ee5753f2e539e4c56626c8d86e50ab40b97ad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 21:00:42 +0000 Subject: [PATCH 5/7] Address code review: update grafana and autoupdate migration to use dynamic keys Co-authored-by: camilamacedo86 <7708031+camilamacedo86@users.noreply.github.com> --- pkg/cli/alpha/internal/generate.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/cli/alpha/internal/generate.go b/pkg/cli/alpha/internal/generate.go index 2276bf7c65f..30af05bb4cf 100644 --- a/pkg/cli/alpha/internal/generate.go +++ b/pkg/cli/alpha/internal/generate.go @@ -240,7 +240,9 @@ func kubebuilderCreate(s store.Store) error { // Migrates the Grafana plugin. func migrateGrafanaPlugin(s store.Store, src, des string) error { var grafanaPlugin struct{} - err := s.Config().DecodePluginConfig(plugin.KeyFor(grafanav1alpha.Plugin{}), grafanaPlugin) + // Use GetPluginKeyForConfig to support custom bundle names + key := plugin.GetPluginKeyForConfig(s.Config().GetPluginChain(), grafanav1alpha.Plugin{}) + err := s.Config().DecodePluginConfig(key, grafanaPlugin) if errors.As(err, &config.PluginKeyNotFoundError{}) { slog.Info("Grafana plugin not found, skipping migration") return nil @@ -261,7 +263,9 @@ func migrateGrafanaPlugin(s store.Store, src, des string) error { func migrateAutoUpdatePlugin(s store.Store) error { var autoUpdatePlugin struct{} - err := s.Config().DecodePluginConfig(plugin.KeyFor(autoupdatev1alpha.Plugin{}), autoUpdatePlugin) + // Use GetPluginKeyForConfig to support custom bundle names + key := plugin.GetPluginKeyForConfig(s.Config().GetPluginChain(), autoupdatev1alpha.Plugin{}) + err := s.Config().DecodePluginConfig(key, autoUpdatePlugin) if errors.As(err, &config.PluginKeyNotFoundError{}) { slog.Info("Auto Update plugin not found, skipping migration") return nil From 5304b6d20456e8c7cf4e213fcdad293762ae2dda Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 21:38:26 +0000 Subject: [PATCH 6/7] Fix gofmt formatting in plugin_test.go Co-authored-by: camilamacedo86 <7708031+camilamacedo86@users.noreply.github.com> --- pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go b/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go index ecda1179c6c..e107c02e924 100644 --- a/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go +++ b/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go @@ -26,7 +26,7 @@ import ( // its key based on the plugin chain, supporting custom bundle names. func TestGetPluginKeyForConfigIntegration(t *testing.T) { p := Plugin{} - + tests := []struct { name string pluginChain []string From dfe90876ea94e0532dff8f39b758f70c6e10b5b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Oct 2025 22:24:28 +0000 Subject: [PATCH 7/7] Run make lint-fix to address linting issues Co-authored-by: camilamacedo86 <7708031+camilamacedo86@users.noreply.github.com> --- pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go b/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go index e107c02e924..24c8a1bac31 100644 --- a/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go +++ b/pkg/plugins/golang/deploy-image/v1alpha1/plugin_test.go @@ -72,7 +72,7 @@ func TestGetPluginKeyForConfigIntegration(t *testing.T) { } for _, tt := range tests { - tt := tt // capture range variable + // capture range variable t.Run(tt.name, func(t *testing.T) { result := plugin.GetPluginKeyForConfig(tt.pluginChain, p) if result != tt.expected {