From e1387f51c561745ab2054b0a72ec58339d451328 Mon Sep 17 00:00:00 2001 From: Azeez Syed Date: Thu, 11 Dec 2025 21:23:02 +0530 Subject: [PATCH] fix: respect --server-side flag in helm upgrade --install Fixes #31627 When using helm upgrade --install on a non-existent release, the --server-side flag was not being respected. This was because the upgrade client uses ServerSideApply as a string ("true", "false", "auto") while the install client uses it as a boolean, and the conversion was missing when creating the install client. This fix adds proper conversion logic to ensure that: - --server-side=true -> install with server-side apply - --server-side=false -> install with client-side apply - --server-side=auto or unset -> default to server-side apply Also adds TestUpgradeInstallServerSideApply to verify the fix works correctly. The test has been enhanced to actually verify the ApplyMethod field on releases to ensure the --server-side flag is properly passed through. Signed-off-by: Azeez Syed --- pkg/cmd/upgrade.go | 11 +++++++++ pkg/cmd/upgrade_test.go | 50 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/pkg/cmd/upgrade.go b/pkg/cmd/upgrade.go index 92f130f60..1f0a009ac 100644 --- a/pkg/cmd/upgrade.go +++ b/pkg/cmd/upgrade.go @@ -154,6 +154,17 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { instClient.HideSecret = client.HideSecret instClient.TakeOwnership = client.TakeOwnership + // Convert ServerSideApply from string (upgrade) to bool (install) + switch client.ServerSideApply { + case "true": + instClient.ServerSideApply = true + case "false": + instClient.ServerSideApply = false + case "auto", "": + // For "auto" or empty, default to true (server-side apply) + instClient.ServerSideApply = true + } + if isReleaseUninstalled(versions) { instClient.Replace = true } diff --git a/pkg/cmd/upgrade_test.go b/pkg/cmd/upgrade_test.go index 8729be0ec..045ccfe5c 100644 --- a/pkg/cmd/upgrade_test.go +++ b/pkg/cmd/upgrade_test.go @@ -605,3 +605,53 @@ func TestUpgradeWithDryRun(t *testing.T) { t.Error("expected error when --hide-secret used without --dry-run") } } + +func TestUpgradeInstallServerSideApply(t *testing.T) { + releaseName := "test-server-side-apply" + chartPath := "testdata/testcharts/chart-with-subchart-notes" + + store := storageFixture() + + // Test that --server-side=false is properly passed to install client + cmd := fmt.Sprintf("upgrade %s -i --server-side=false '%s'", releaseName, chartPath) + _, _, err := executeActionCommandC(store, cmd) + if err != nil { + t.Errorf("unexpected error with --server-side=false: %v", err) + } + + // Verify the release was created and check ApplyMethod + reli, err := store.Get(releaseName, 1) + if err != nil { + t.Errorf("failed to get release: %v", err) + } + rel, err := releaserToV1Release(reli) + if err != nil { + t.Errorf("failed to convert release to *release.Release: %v", err) + } + // Check that ApplyMethod is not "ssa" (should be client-side apply) + if rel.ApplyMethod == "ssa" { + t.Errorf("expected release to use client-side apply, but ApplyMethod is 'ssa'") + } + + // Test that --server-side=true is properly passed to install client + releaseName2 := "test-server-side-apply-true" + cmd = fmt.Sprintf("upgrade %s -i --server-side=true '%s'", releaseName2, chartPath) + _, _, err = executeActionCommandC(store, cmd) + if err != nil { + t.Errorf("unexpected error with --server-side=true: %v", err) + } + + // Verify the release was created and check ApplyMethod + reli2, err := store.Get(releaseName2, 1) + if err != nil { + t.Errorf("failed to get release: %v", err) + } + rel2, err := releaserToV1Release(reli2) + if err != nil { + t.Errorf("failed to convert release to *release.Release: %v", err) + } + // Check that ApplyMethod is "ssa" (server-side apply) + if rel2.ApplyMethod != "ssa" { + t.Errorf("expected release to use server-side apply, but ApplyMethod is '%s'", rel2.ApplyMethod) + } +}