Skip to content

Commit f437802

Browse files
committed
fix: add --dry-run=server to helm diff for Helm 4
Helm 4 changed DryRun from boolean to DryRunStrategy enum. The helm-diff plugin now requires --dry-run=server for .Capabilities.APIVersions.Has to work correctly during diffs. Closes #991
1 parent 83b6baf commit f437802

3 files changed

Lines changed: 146 additions & 20 deletions

File tree

internal/app/release.go

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -187,29 +187,32 @@ func (r *Release) uninstall(p *plan, optionalNamespace ...string) {
187187
p.addCommand(cmd, priority, r, before, after)
188188
}
189189

190+
// getDiffArgs returns the helm arguments for diffing a release
191+
func (r *Release) getDiffArgs() []string {
192+
if flags.kubectlDiff {
193+
return r.getHelmArgsFor("template")
194+
}
195+
args := []string{"diff"}
196+
if !flags.showSecrets {
197+
args = append(args, "--suppress-secrets")
198+
}
199+
if flags.noColors {
200+
args = append(args, "--no-color")
201+
}
202+
if flags.diffContext != -1 {
203+
args = append(args, "--context", strconv.Itoa(flags.diffContext))
204+
}
205+
if checkHelmVersion(">=4.0.0") {
206+
args = append(args, "--dry-run=server")
207+
}
208+
return concat(args, r.getHelmArgsFor("diff"))
209+
}
210+
190211
// diffRelease diffs an existing release with the specified values.yaml
191212
func (r *Release) diff() (string, error) {
192-
var (
193-
args []string
194-
maxExitCode int
195-
)
196-
197-
if !flags.kubectlDiff {
198-
args = []string{"diff"}
199-
if !flags.showSecrets {
200-
args = append(args, "--suppress-secrets")
201-
}
202-
if flags.noColors {
203-
args = append(args, "--no-color")
204-
}
205-
if flags.diffContext != -1 {
206-
args = append(args, "--context", strconv.Itoa(flags.diffContext))
207-
}
208-
args = concat(args, r.getHelmArgsFor("diff"))
209-
} else {
210-
args = r.getHelmArgsFor("template")
211-
}
213+
var maxExitCode int
212214

215+
args := r.getDiffArgs()
213216
desc := "Diffing release [ " + r.Name + " ] in namespace [ " + r.Namespace + " ]"
214217
cmd := CmdPipe{helmCmd(args, desc)}
215218

internal/app/release_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,3 +566,73 @@ func Test_release_getChartVersion(t *testing.T) {
566566
})
567567
}
568568
}
569+
570+
func Test_release_getDiffArgs(t *testing.T) {
571+
// Save original values to restore after test
572+
originalHelmVersion := curHelmVersion
573+
originalFlags := flags
574+
defer func() {
575+
curHelmVersion = originalHelmVersion
576+
flags = originalFlags
577+
}()
578+
579+
r := &Release{
580+
Name: "test-release",
581+
Namespace: "test-ns",
582+
Chart: "repo/chart",
583+
Version: "1.0.0",
584+
}
585+
586+
tests := []struct {
587+
name string
588+
helmVersion string
589+
wantFlag string
590+
shouldHave bool
591+
}{
592+
{
593+
name: "helm 4.0.0 should have --dry-run=server",
594+
helmVersion: "v4.0.0",
595+
wantFlag: "--dry-run=server",
596+
shouldHave: true,
597+
},
598+
{
599+
name: "helm 4.1.0 should have --dry-run=server",
600+
helmVersion: "v4.1.0",
601+
wantFlag: "--dry-run=server",
602+
shouldHave: true,
603+
},
604+
{
605+
name: "helm 3.14.0 should not have --dry-run=server",
606+
helmVersion: "v3.14.0",
607+
wantFlag: "--dry-run=server",
608+
shouldHave: false,
609+
},
610+
{
611+
name: "helm 3.99.99 should not have --dry-run=server",
612+
helmVersion: "v3.99.99",
613+
wantFlag: "--dry-run=server",
614+
shouldHave: false,
615+
},
616+
}
617+
618+
for _, tt := range tests {
619+
t.Run(tt.name, func(t *testing.T) {
620+
curHelmVersion = tt.helmVersion
621+
flags = cli{}
622+
623+
args := r.getDiffArgs()
624+
hasFlag := false
625+
for _, arg := range args {
626+
if arg == tt.wantFlag {
627+
hasFlag = true
628+
break
629+
}
630+
}
631+
632+
if hasFlag != tt.shouldHave {
633+
t.Errorf("getDiffArgs() with helm %s: got flag %s present=%v, want present=%v. Args: %v",
634+
tt.helmVersion, tt.wantFlag, hasFlag, tt.shouldHave, args)
635+
}
636+
})
637+
}
638+
}

internal/app/utils_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,56 @@ func Test_eyamlSecrets(t *testing.T) {
285285
})
286286
}
287287
}
288+
289+
func Test_checkVersion(t *testing.T) {
290+
tests := []struct {
291+
name string
292+
version string
293+
constraint string
294+
want bool
295+
}{
296+
{
297+
name: "helm 4.0.0 matches >=4.0.0",
298+
version: "v4.0.0",
299+
constraint: ">=4.0.0",
300+
want: true,
301+
},
302+
{
303+
name: "helm 4.1.0 matches >=4.0.0",
304+
version: "v4.1.0",
305+
constraint: ">=4.0.0",
306+
want: true,
307+
},
308+
{
309+
name: "helm 3.14.0 does not match >=4.0.0",
310+
version: "v3.14.0",
311+
constraint: ">=4.0.0",
312+
want: false,
313+
},
314+
{
315+
name: "helm 3.99.99 does not match >=4.0.0",
316+
version: "v3.99.99",
317+
constraint: ">=4.0.0",
318+
want: false,
319+
},
320+
{
321+
name: "helm 4.0.0 does not match <4.0.0",
322+
version: "v4.0.0",
323+
constraint: "<4.0.0",
324+
want: false,
325+
},
326+
{
327+
name: "helm 3.14.0 matches <4.0.0",
328+
version: "v3.14.0",
329+
constraint: "<4.0.0",
330+
want: true,
331+
},
332+
}
333+
for _, tt := range tests {
334+
t.Run(tt.name, func(t *testing.T) {
335+
if got := checkVersion(tt.version, tt.constraint); got != tt.want {
336+
t.Errorf("checkVersion(%s, %s) = %v, want %v", tt.version, tt.constraint, got, tt.want)
337+
}
338+
})
339+
}
340+
}

0 commit comments

Comments
 (0)