fix: include-needs should only include direct dependencies, not transitive

Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
yxxhero 2026-03-15 15:33:45 +08:00 committed by yxxhero
parent b06d390ade
commit 869a3c92c1
14 changed files with 98 additions and 98 deletions

View File

@ -2354,10 +2354,11 @@ func (a *App) withNeeds(r *Run, c DAGConfig, includeDisabled bool, f func(*state
if len(toRender) > 0 {
// toRender already contains the direct and transitive needs depending on the DAG options.
// That's why we don't pass in `IncludeNeeds: c.IncludeNeeds(), IncludeTransitiveNeeds: c.IncludeTransitiveNeeds()` here.
// That's why we don't pass in `IncludeNeeds` or `IncludeTransitiveNeeds` here.
// 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.
if _, errs := withDAG(st, r.helm, a.Logger, state.PlanOptions{SelectedReleases: toRender, Reverse: false, SkipNeeds: c.SkipNeeds(), IncludeNeeds: includeNeeds}, a.WrapWithoutSelector(func(subst *state.HelmState, helm helmexec.Interface) []error {
// 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 {
rels = append(rels, subst.Releases...)
return nil
})); len(errs) > 0 {

View File

@ -29,15 +29,11 @@ Affected releases are:
serviceB (my/chart) UPDATED
serviceC (my/chart) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 1 groups of releases in this order:
GROUP RELEASES
1 default//serviceA
2 default//serviceB
3 default//serviceC
invoking preapply hooks for releases in group 1/3: default//serviceA
invoking preapply hooks for releases in group 2/3: default//serviceB
invoking preapply hooks for releases in group 3/3: default//serviceC
invoking preapply hooks for releases in group 1/1: default//serviceA
processing 3 groups of releases in this order:
GROUP RELEASES
1 default//serviceC

View File

@ -33,28 +33,23 @@ Affected releases are:
kubernetes-external-secrets (incubator/raw) UPDATED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/default/my-release
2 default/default/external-secrets
3 default/kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/default/my-release
invoking preapply hooks for releases in group 2/3: default/default/external-secrets
invoking preapply hooks for releases in group 3/3: default/kube-system/kubernetes-external-secrets
processing 3 groups of releases in this order:
invoking preapply hooks for releases in group 1/2: default/default/my-release
invoking preapply hooks for releases in group 2/2: default/default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/kube-system/kubernetes-external-secrets
2 default/default/external-secrets
3 default/default/my-release
1 default/default/external-secrets
2 default/default/my-release
processing releases in group 1/3: default/kube-system/kubernetes-external-secrets
processing releases in group 2/3: default/default/external-secrets
processing releases in group 3/3: default/default/my-release
processing releases in group 1/2: default/default/external-secrets
processing releases in group 2/2: default/default/my-release
UPDATED RELEASES:
NAME NAMESPACE CHART VERSION DURATION
kubernetes-external-secrets kube-system incubator/raw 3.1.0 0s
external-secrets default incubator/raw 3.1.0 0s
my-release default incubator/raw 3.1.0 0s
NAME NAMESPACE CHART VERSION DURATION
external-secrets default incubator/raw 3.1.0 0s
my-release default incubator/raw 3.1.0 0s

View File

@ -32,15 +32,13 @@ Affected releases are:
external-secrets (incubator/raw) UPDATED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/default/my-release
2 default/default/external-secrets
3 default/kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/default/my-release
invoking preapply hooks for releases in group 2/3: default/default/external-secrets
invoking preapply hooks for releases in group 3/3: default/kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/2: default/default/my-release
invoking preapply hooks for releases in group 2/2: default/default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/default/external-secrets

View File

@ -36,20 +36,20 @@ Affected releases are:
kubernetes-external-secrets (incubator/raw) DELETED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/default/my-release
2 default/default/external-secrets
3 default/kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/default/my-release
invoking preapply hooks for releases in group 2/3: default/default/external-secrets
invoking preapply hooks for releases in group 3/3: default/kube-system/kubernetes-external-secrets
processing 1 groups of releases in this order:
invoking preapply hooks for releases in group 1/2: default/default/my-release
invoking preapply hooks for releases in group 2/2: default/default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/kube-system/kubernetes-external-secrets
1 default/default/my-release
2 default/default/external-secrets
processing releases in group 1/1: default/kube-system/kubernetes-external-secrets
processing releases in group 1/2: default/default/my-release
processing releases in group 2/2: default/default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/default/external-secrets
@ -64,8 +64,3 @@ NAME NAMESPACE CHART VERSION DURATION
external-secrets default incubator/raw 3.1.0 0s
my-release default incubator/raw 3.1.0 0s
DELETED RELEASES:
NAME NAMESPACE DURATION
kubernetes-external-secrets kube-system 0s

View File

@ -35,15 +35,13 @@ Affected releases are:
external-secrets (incubator/raw) UPDATED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/default/my-release
2 default/default/external-secrets
3 default/kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/default/my-release
invoking preapply hooks for releases in group 2/3: default/default/external-secrets
invoking preapply hooks for releases in group 3/3: default/kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/2: default/default/my-release
invoking preapply hooks for releases in group 2/2: default/default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/default/external-secrets

View File

@ -38,11 +38,13 @@ GROUP RELEASES
invoking preapply hooks for releases in group 1/2: default/default/my-release
invoking preapply hooks for releases in group 2/2: default/default/external-secrets
processing 1 groups of releases in this order:
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/default/external-secrets
2 default/default/my-release
processing releases in group 1/1: default/default/external-secrets
processing releases in group 1/2: default/default/external-secrets
processing releases in group 2/2: default/default/my-release
UPDATED RELEASES:
NAME NAMESPACE CHART VERSION DURATION

View File

@ -33,28 +33,23 @@ Affected releases are:
kubernetes-external-secrets (incubator/raw) UPDATED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/my-release
2 default/external-secrets
3 kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/my-release
invoking preapply hooks for releases in group 2/3: default/external-secrets
invoking preapply hooks for releases in group 3/3: kube-system/kubernetes-external-secrets
processing 3 groups of releases in this order:
invoking preapply hooks for releases in group 1/2: default/my-release
invoking preapply hooks for releases in group 2/2: default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 kube-system/kubernetes-external-secrets
2 default/external-secrets
3 default/my-release
1 default/external-secrets
2 default/my-release
processing releases in group 1/3: kube-system/kubernetes-external-secrets
processing releases in group 2/3: default/external-secrets
processing releases in group 3/3: default/my-release
processing releases in group 1/2: default/external-secrets
processing releases in group 2/2: default/my-release
UPDATED RELEASES:
NAME NAMESPACE CHART VERSION DURATION
kubernetes-external-secrets kube-system incubator/raw 3.1.0 0s
external-secrets default incubator/raw 3.1.0 0s
my-release default incubator/raw 3.1.0 0s
NAME NAMESPACE CHART VERSION DURATION
external-secrets default incubator/raw 3.1.0 0s
my-release default incubator/raw 3.1.0 0s

View File

@ -32,15 +32,13 @@ Affected releases are:
external-secrets (incubator/raw) UPDATED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/my-release
2 default/external-secrets
3 kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/my-release
invoking preapply hooks for releases in group 2/3: default/external-secrets
invoking preapply hooks for releases in group 3/3: kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/2: default/my-release
invoking preapply hooks for releases in group 2/2: default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/external-secrets

View File

@ -36,20 +36,20 @@ Affected releases are:
kubernetes-external-secrets (incubator/raw) DELETED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/my-release
2 default/external-secrets
3 kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/my-release
invoking preapply hooks for releases in group 2/3: default/external-secrets
invoking preapply hooks for releases in group 3/3: kube-system/kubernetes-external-secrets
processing 1 groups of releases in this order:
invoking preapply hooks for releases in group 1/2: default/my-release
invoking preapply hooks for releases in group 2/2: default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 kube-system/kubernetes-external-secrets
1 default/my-release
2 default/external-secrets
processing releases in group 1/1: kube-system/kubernetes-external-secrets
processing releases in group 1/2: default/my-release
processing releases in group 2/2: default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/external-secrets
@ -64,8 +64,3 @@ NAME NAMESPACE CHART VERSION DURATION
external-secrets default incubator/raw 3.1.0 0s
my-release default incubator/raw 3.1.0 0s
DELETED RELEASES:
NAME NAMESPACE DURATION
kubernetes-external-secrets kube-system 0s

View File

@ -35,15 +35,13 @@ Affected releases are:
external-secrets (incubator/raw) UPDATED
my-release (incubator/raw) UPDATED
invoking preapply hooks for 3 groups of releases in this order:
invoking preapply hooks for 2 groups of releases in this order:
GROUP RELEASES
1 default/my-release
2 default/external-secrets
3 kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/3: default/my-release
invoking preapply hooks for releases in group 2/3: default/external-secrets
invoking preapply hooks for releases in group 3/3: kube-system/kubernetes-external-secrets
invoking preapply hooks for releases in group 1/2: default/my-release
invoking preapply hooks for releases in group 2/2: default/external-secrets
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/external-secrets

View File

@ -38,11 +38,13 @@ GROUP RELEASES
invoking preapply hooks for releases in group 1/2: default/my-release
invoking preapply hooks for releases in group 2/2: default/external-secrets
processing 1 groups of releases in this order:
processing 2 groups of releases in this order:
GROUP RELEASES
1 default/external-secrets
2 default/my-release
processing releases in group 1/1: default/external-secrets
processing releases in group 1/2: default/external-secrets
processing releases in group 2/2: default/my-release
UPDATED RELEASES:
NAME NAMESPACE CHART VERSION DURATION

View File

@ -3048,7 +3048,7 @@ func unmarkNeedsAndTransitives(filteredReleases []Release, allReleases []Release
func unmarkNeedsDirectOnly(filteredReleases []Release) {
directNeeds := collectDirectNeedsOnly(filteredReleases)
unmarkReleases(directNeeds, filteredReleases)
unmarkReleasesByNeedID(directNeeds, filteredReleases)
}
func collectDirectNeedsOnly(filteredReleases []Release) map[string]struct{} {
@ -3063,6 +3063,18 @@ func collectDirectNeedsOnly(filteredReleases []Release) map[string]struct{} {
return directNeeds
}
func unmarkReleasesByNeedID(toUnmark map[string]struct{}, releases []Release) {
for needID := range toUnmark {
parts := strings.Split(needID, "/")
needName := parts[len(parts)-1]
for i, r := range releases {
if r.Name == needName {
releases[i].Filtered = false
}
}
}
}
func collectAllNeedsWithTransitives(filteredReleases []Release, allReleases []ReleaseSpec) map[string]struct{} {
needsWithTranstives := map[string]struct{}{}
for _, r := range filteredReleases {

View File

@ -132,6 +132,12 @@ func SortedReleaseGroups(releases []Release, opts PlanOptions) ([][]Release, err
func GroupReleasesByDependency(releases []Release, opts PlanOptions) ([][]Release, error) {
idToReleases := map[string][]Release{}
idToIndex := map[string]int{}
nameToID := map[string]string{}
for _, r := range releases {
id := ReleaseToID(&r.ReleaseSpec)
nameToID[r.Name] = id
}
d := dag.New()
for i, r := range releases {
@ -143,7 +149,11 @@ func GroupReleasesByDependency(releases []Release, opts PlanOptions) ([][]Releas
var needs []string
for i := 0; i < len(r.Needs); i++ {
n := r.Needs[i]
needs = append(needs, n)
if fullID, ok := nameToID[n]; ok {
needs = append(needs, fullID)
} else {
needs = append(needs, n)
}
}
d.Add(id, dag.Dependencies(needs))
}
@ -154,17 +164,22 @@ func GroupReleasesByDependency(releases []Release, opts PlanOptions) ([][]Releas
}
var selectedReleaseIDs []string
for _, r := range releases {
if !r.Filtered {
id := ReleaseToID(&r.ReleaseSpec)
selectedReleaseIDs = append(selectedReleaseIDs, id)
}
}
for _, r := range opts.SelectedReleases {
release := r
id := ReleaseToID(&release)
selectedReleaseIDs = append(selectedReleaseIDs, id)
skipDepValidation := opts.SkipNeeds
if opts.IncludeNeeds && !opts.IncludeTransitiveNeeds {
skipDepValidation = true
}
plan, err := d.Plan(dag.SortOptions{
Only: selectedReleaseIDs,
WithDependencies: opts.IncludeNeeds || opts.IncludeTransitiveNeeds,
WithoutDependencies: opts.SkipNeeds,
WithDependencies: false,
WithoutDependencies: skipDepValidation,
})
if err != nil {
if ude, ok := err.(*dag.UnhandledDependencyError); ok {