diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index 7ea87166c..12c96f50c 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -27,10 +27,10 @@ import ( "github.com/Masterminds/semver/v3" "github.com/pkg/errors" - "github.com/Masterminds/vcs" "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/gates" + "helm.sh/helm/v3/pkg/gitutils" "helm.sh/helm/v3/pkg/helmpath" "helm.sh/helm/v3/pkg/provenance" "helm.sh/helm/v3/pkg/registry" @@ -39,6 +39,8 @@ import ( const FeatureGateOCI = gates.Gate("HELM_EXPERIMENTAL_OCI") +var hasGitReference = gitutils.HasGitReference + // Resolver resolves dependencies from semantic version ranges to a particular version. type Resolver struct { chartpath string @@ -113,18 +115,12 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string if strings.HasPrefix(d.Repository, "git://") { - local, err := os.MkdirTemp("", d.Name) - if err != nil { - return nil, err - } - repo, err := vcs.NewRepo(strings.TrimPrefix(d.Repository, "git://"), local) + found, err := hasGitReference(strings.TrimPrefix(d.Repository, "git://"), d.Version, d.Name) if err != nil { return nil, err } - found := repo.IsReference(d.Version) - if !found { return nil, fmt.Errorf(`dependency %q is missing git branch or tag: %s. When using a "git://" type repository, the "version" should be a valid branch or tag name`, d.Name, d.Version) diff --git a/internal/resolver/resolver_test.go b/internal/resolver/resolver_test.go index 6c9c81c77..54fbf939f 100644 --- a/internal/resolver/resolver_test.go +++ b/internal/resolver/resolver_test.go @@ -23,7 +23,16 @@ import ( "helm.sh/helm/v3/pkg/registry" ) +func fakeGitReference(gitRepo, ref, repoName string) (bool, error) { + gitRefs := map[string]string{ + "1.0.0": "", + } + + _, found := gitRefs[ref] + return found, nil +} func TestResolve(t *testing.T) { + hasGitReference = fakeGitReference tests := []struct { name string req []*chart.Dependency @@ -138,25 +147,49 @@ func TestResolve(t *testing.T) { err: true, }, { - name: "repo from git ssh url", + name: "repo from git https url", req: []*chart.Dependency{ - {Name: "gitdependency", Repository: "git://git@github.com:helm/gitdependency.git", Version: "1.0.0"}, + {Name: "gitdependencyok", Repository: "git://https://github.com/helm/helmchart.git", Version: "1.0.0"}, }, expect: &chart.Lock{ Dependencies: []*chart.Dependency{ - {Name: "gitdependency", Repository: "git://git@github.com:helm/gitdependency.git", Version: "1.0.0"}, + {Name: "gitdependencyok", Repository: "git://https://github.com/helm/helmchart.git", Version: "1.0.0"}, }, }, - err: true, + err: false, }, { name: "repo from git https url", req: []*chart.Dependency{ - {Name: "gitdependency", Repository: "git://https://github.com/helm/gitdependency.git", Version: "1.0.0"}, + {Name: "gitdependencyerror", Repository: "git://https://github.com/helm/helmchart.git", Version: "2.0.0"}, + }, + expect: &chart.Lock{ + Dependencies: []*chart.Dependency{ + {Name: "gitdependencyerror", Repository: "git://https://github.com/helm/helmchart.git", Version: "2.0.0"}, + }, + }, + err: true, + }, + { + name: "repo from git ssh url", + req: []*chart.Dependency{ + {Name: "gitdependency", Repository: "git://git@github.com:helm/helmchart.git", Version: "1.0.0"}, + }, + expect: &chart.Lock{ + Dependencies: []*chart.Dependency{ + {Name: "gitdependency", Repository: "git://git@github.com:helm/helmchart.git", Version: "1.0.0"}, + }, + }, + err: false, + }, + { + name: "repo from git ssh url", + req: []*chart.Dependency{ + {Name: "gitdependencyerror", Repository: "git://git@github.com:helm/helmchart.git", Version: "2.0.0"}, }, expect: &chart.Lock{ Dependencies: []*chart.Dependency{ - {Name: "gitdependency", Repository: "git://https://github.com/helm/gitdependency.git", Version: "1.0.0"}, + {Name: "gitdependencyerror", Repository: "git://git@github.com:helm/helmchart.git", Version: "2.0.0"}, }, }, err: true, diff --git a/pkg/getter/gitgetter.go b/pkg/getter/gitgetter.go index 40ec4833f..e234e5a47 100644 --- a/pkg/getter/gitgetter.go +++ b/pkg/getter/gitgetter.go @@ -24,6 +24,7 @@ import ( "path/filepath" "github.com/Masterminds/vcs" + "helm.sh/helm/v3/internal/fileutil" ) diff --git a/pkg/gitutils/gitutils.go b/pkg/gitutils/gitutils.go new file mode 100644 index 000000000..1795caf68 --- /dev/null +++ b/pkg/gitutils/gitutils.go @@ -0,0 +1,47 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/*Package engine implements the Go text template engine as needed for Helm. + +When Helm renders templates it does so with additional functions and different +modes (e.g., strict, lint mode). This package handles the helm specific +implementation. +*/ +package gitutils + +import ( + "os" + + "github.com/Masterminds/vcs" +) + +func HasGitReference(gitRepo, ref, repoName string) (bool, error) { + local, err := os.MkdirTemp("", repoName) + if err != nil { + return false, err + } + repo, err := vcs.NewRepo(gitRepo, local) + + if err != nil { + return false, err + } + + if err := repo.Get(); err != nil { + return false, err + } + defer os.RemoveAll(local) + return repo.IsReference(ref), nil +}