From ded47185234d1329e71de364707a7db76acd72f0 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 4 Aug 2026 19:30:11 +0300 Subject: [PATCH] fix: align index loading with upstream Helm v4 Signed-off-by: Stefan Prodan --- internal/helm/chart/dependency_manager.go | 6 ++++- .../helm/chart/dependency_manager_test.go | 14 +++++++++++ internal/helm/repository/chart_repository.go | 1 + .../helm/repository/chart_repository_test.go | 24 +++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/internal/helm/chart/dependency_manager.go b/internal/helm/chart/dependency_manager.go index 93745123b..6fb9b2ed0 100644 --- a/internal/helm/chart/dependency_manager.go +++ b/internal/helm/chart/dependency_manager.go @@ -153,11 +153,15 @@ func (dm *DependencyManager) build(ctx context.Context, ref Reference, c *helmch sem := semaphore.NewWeighted(current) c := &chartWithLock{Chart: c} for name, dep := range deps { - name, dep := name, dep if err := sem.Acquire(groupCtx, 1); err != nil { return err } group.Go(func() (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("failed to add dependency '%s': %v", name, r) + } + }() defer sem.Release(1) if isLocalDep(dep) { localRef, ok := ref.(LocalReference) diff --git a/internal/helm/chart/dependency_manager_test.go b/internal/helm/chart/dependency_manager_test.go index 11b78e422..b0fe8ab2b 100644 --- a/internal/helm/chart/dependency_manager_test.go +++ b/internal/helm/chart/dependency_manager_test.go @@ -281,6 +281,20 @@ func TestDependencyManager_build(t *testing.T) { } } +func TestDependencyManager_build_PanicRecovery(t *testing.T) { + g := NewWithT(t) + + dm := NewDependencyManager(WithDownloaderCallback(func(url string) (repository.Downloader, error) { + panic("downloader callback error") + })) + err := dm.build(context.TODO(), LocalReference{}, &helmchart.Chart{}, map[string]*helmchart.Dependency{ + "example": {Repository: "https://example.com"}, + }) + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(ContainSubstring("failed to add dependency 'example'")) + g.Expect(err.Error()).To(ContainSubstring("downloader callback error")) +} + func TestDependencyManager_addLocalDependency(t *testing.T) { tests := []struct { name string diff --git a/internal/helm/repository/chart_repository.go b/internal/helm/repository/chart_repository.go index 1459ca1e4..4e2f7dfc4 100644 --- a/internal/helm/repository/chart_repository.go +++ b/internal/helm/repository/chart_repository.go @@ -90,6 +90,7 @@ func IndexFromBytes(b []byte) (*repo.IndexFile, error) { for name, cvs := range i.Entries { for idx := len(cvs) - 1; idx >= 0; idx-- { if cvs[idx] == nil { + cvs = append(cvs[:idx], cvs[idx+1:]...) continue } // When metadata section missing, initialize with no data diff --git a/internal/helm/repository/chart_repository_test.go b/internal/helm/repository/chart_repository_test.go index 53301cdb6..c9aadf8a2 100644 --- a/internal/helm/repository/chart_repository_test.go +++ b/internal/helm/repository/chart_repository_test.go @@ -828,6 +828,22 @@ entries: home: https://github.com/something/else digest: "sha256:1234567890abcdef" ` +var indexWithEmptyEntries = ` +apiVersion: v1 +entries: + nginx: + - null + - urls: + - https://charts.helm.sh/stable/nginx-0.2.0.tgz + name: nginx + description: string + version: 0.2.0 + home: https://github.com/something/else + digest: "sha256:1234567890abcdef" + - null + alpine: + - null +` var indexWithLastVersionInvalid = ` apiVersion: v1 entries: @@ -862,6 +878,10 @@ func TestIndexFromBytes_InvalidEntries(t *testing.T) { source: "indexWithLastVersionInvalid", data: indexWithLastVersionInvalid, }, + { + source: "indexWithEmptyEntries", + data: indexWithEmptyEntries, + }, } for _, tc := range tests { t.Run(tc.source, func(t *testing.T) { @@ -874,6 +894,10 @@ func TestIndexFromBytes_InvalidEntries(t *testing.T) { t.Error("expected one chart version not to be filtered out") } for _, v := range cvs { + if v == nil { + t.Error("empty entry was not filtered out") + continue + } if v.Version == "0..1.0" { t.Error("malformed version was not filtered out") }