fix: prevent duplicate disabled releases in withDAG for Diff command

When running helmfile diff with releases that have 'installed: false',
(flagging them as to-be-uninstalled), the release was being disabled
flag would be included in toRender. Later, these disabled releases were
added again via releasesToUninstall when includeDisabled is true,
causing them to appear twice in the final releases list.

This resulted in duplicate 'Listing releases' log messages and
potentially duplicate helm list calls.

The fix filters out disabled releases from toRender before passing it
to withDAG. This ensures disabled releases are only included once
in the final list (via releasesToUninstall at line 2378-2382).

Fixes the test failure in test/integration/test-cases/diff-args
where 'Listing releases matching ^uninstalled$' appeared twice
instead of once.

Note: diff-live-stderr still shows two messages because that test
was updated separately to match that behavior (with trailing spaces).
The non-live diff should now correctly shows only one message.

Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
yxxhero 2026-03-17 07:04:22 +08:00 committed by yxxhero
parent 20928620a8
commit f2e6c9a7ac
1 changed files with 11 additions and 1 deletions

View File

@ -2358,7 +2358,17 @@ func (a *App) withNeeds(r *Run, c DAGConfig, includeDisabled bool, f func(*state
// Otherwise, in case include-needs=true, it will include the needs of needs, which results in unexpectedly introducing transitive needs,
// even if include-transitive-needs=true is unspecified.
// We also set SkipNeeds=true because toRender already contains all the needs we want to process.
if _, errs := withDAG(st, r.helm, a.Logger, state.PlanOptions{SelectedReleases: toRender, Reverse: false, SkipNeeds: true}, a.WrapWithoutSelector(func(subst *state.HelmState, helm helmexec.Interface) []error {
//
// IMPORTANT: Filter out disabled releases from toRender to avoid duplicates.
// Disabled releases will be added back later via releasesToUninstall if includeDisabled is true.
var enabledToRender []state.ReleaseSpec
for _, r := range toRender {
if r.Desired() {
enabledToRender = append(enabledToRender, r)
}
}
if _, errs := withDAG(st, r.helm, a.Logger, state.PlanOptions{SelectedReleases: enabledToRender, Reverse: false, SkipNeeds: true}, a.WrapWithoutSelector(func(subst *state.HelmState, helm helmexec.Interface) []error {
rels = append(rels, subst.Releases...)
return nil
})); len(errs) > 0 {