From da82b7c2a4f7430a2aaf5bca7aa50f1fb1fff9bb Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 18 May 2026 13:54:03 -0400 Subject: [PATCH] fix(wfctl): preserve iac provider plan metadata --- cmd/wfctl/plugin_install.go | 2 ++ cmd/wfctl/plugin_install_e2e_test.go | 48 ++++++++++++++++++++++++++++ cmd/wfctl/plugin_registry.go | 6 ++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/cmd/wfctl/plugin_install.go b/cmd/wfctl/plugin_install.go index b7db65ed..f42de9a3 100644 --- a/cmd/wfctl/plugin_install.go +++ b/cmd/wfctl/plugin_install.go @@ -1362,6 +1362,7 @@ type installedPluginJSON struct { Tags []string `json:"tags,omitempty"` Type string `json:"type,omitempty"` Capabilities *installedPluginCapabilities `json:"capabilities,omitempty"` + IaCProvider *RegistryIaCProvider `json:"iacProvider,omitempty"` } type installedPluginCapabilities struct { @@ -1395,6 +1396,7 @@ func writeInstalledManifest(path string, m *RegistryManifest) error { Tier: m.Tier, Tags: m.Keywords, Type: m.Type, + IaCProvider: m.IaCProvider, } if m.Capabilities != nil { pj.Capabilities = &installedPluginCapabilities{ diff --git a/cmd/wfctl/plugin_install_e2e_test.go b/cmd/wfctl/plugin_install_e2e_test.go index 5205bc22..bdcb71c1 100644 --- a/cmd/wfctl/plugin_install_e2e_test.go +++ b/cmd/wfctl/plugin_install_e2e_test.go @@ -478,6 +478,54 @@ func TestInstalledManifestPreservesCLICommandsAndBuildHooks(t *testing.T) { } } +// TestInstalledManifestPreservesIaCProviderComputePlanVersion is the regression +// test for workflow#699 manifest metadata: writeInstalledManifest used to drop +// top-level iacProvider.computePlanVersion, so installed IaC provider manifests +// emitted v1/v2 deprecation warnings even when the registry declared v2. +func TestInstalledManifestPreservesIaCProviderComputePlanVersion(t *testing.T) { + rm := &RegistryManifest{ + Name: "workflow-plugin-digitalocean", + Version: "2.0.0", + Author: "tester", + Description: "regression: iacProvider.computePlanVersion preserved post-install", + Type: "external", + Tier: "community", + License: "MIT", + Capabilities: &RegistryCapabilities{ + ModuleTypes: []string{"iac.provider"}, + IaCProvider: &RegistryIaCProvider{ + Name: "digitalocean", + }, + }, + IaCProvider: &RegistryIaCProvider{ + ComputePlanVersion: "v2", + }, + } + + dir := t.TempDir() + path := filepath.Join(dir, "plugin.json") + if err := writeInstalledManifest(path, rm); err != nil { + t.Fatalf("writeInstalledManifest: %v", err) + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read installed plugin.json: %v", err) + } + var got struct { + IaCProvider *RegistryIaCProvider `json:"iacProvider"` + } + if err := json.Unmarshal(data, &got); err != nil { + t.Fatalf("unmarshal installed plugin.json: %v", err) + } + if got.IaCProvider == nil { + t.Fatal("expected top-level iacProvider") + } + if got.IaCProvider.ComputePlanVersion != "v2" { + t.Fatalf("computePlanVersion = %q, want v2", got.IaCProvider.ComputePlanVersion) + } +} + // TestInstalledManifestEngineValidation verifies that the plugin.json written by // writeInstalledManifest passes the engine's plugin.LoadManifest and Validate. func TestInstalledManifestEngineValidation(t *testing.T) { diff --git a/cmd/wfctl/plugin_registry.go b/cmd/wfctl/plugin_registry.go index 7a171ce0..03455e99 100644 --- a/cmd/wfctl/plugin_registry.go +++ b/cmd/wfctl/plugin_registry.go @@ -37,6 +37,7 @@ type RegistryManifest struct { Keywords []string `json:"keywords,omitempty"` Homepage string `json:"homepage,omitempty"` Capabilities *RegistryCapabilities `json:"capabilities,omitempty"` + IaCProvider *RegistryIaCProvider `json:"iacProvider,omitempty"` Contracts []pluginContractDescriptor `json:"contracts,omitempty"` Downloads []PluginDownload `json:"downloads,omitempty"` Assets *PluginAssets `json:"assets,omitempty"` @@ -75,8 +76,9 @@ type RegistryCLICommand struct { // installed plugin.json to match a requested provider name (e.g. "digitalocean") // to a plugin directory. type RegistryIaCProvider struct { - Name string `json:"name"` - ResourceTypes []string `json:"resourceTypes,omitempty"` + Name string `json:"name,omitempty"` + ResourceTypes []string `json:"resourceTypes,omitempty"` + ComputePlanVersion string `json:"computePlanVersion,omitempty"` } // PluginDownload describes a platform-specific binary download for a plugin.