From 94438a596901a2722b51e4259d169919789ee6cb Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 1 Oct 2023 15:10:39 -0400 Subject: [PATCH] add allow-unresolved-version go-proxy config option (#8) Signed-off-by: Alex Goodman --- README.md | 7 ++++--- tool/goproxy/version_resolver.go | 26 +++++++++++++++++++++----- tool/goproxy/version_resolver_test.go | 23 +++++++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index eaec5d1..ab798f4 100644 --- a/README.md +++ b/README.md @@ -205,9 +205,10 @@ The `version.want` option allows a special entry: The `go-proxy` version method reaches out to `proxy.golang.org` to determine the latest version of a Go module. It requires the following configuration options: -| Option | Description | -|--------|--------------------------------------------------------------------------------------------------| -| `module` | The FQDN to the Go module (e.g. `github.com/anchore/syft`) | +| Option | Description | +|--------|----------------------------------------------------------------------------------------------------------------------| +| `module` | The FQDN to the Go module (e.g. `github.com/anchore/syft`) | +| `allow-unresolved-version` | If the latest version cannot be found by the proxy allow for "latest" as a valid value (which `go install` supports) | The `version.want` option allows a special entry: - `latest`: don't pin to a version, use the latest available diff --git a/tool/goproxy/version_resolver.go b/tool/goproxy/version_resolver.go index 6b63ba3..5170887 100644 --- a/tool/goproxy/version_resolver.go +++ b/tool/goproxy/version_resolver.go @@ -11,6 +11,8 @@ import ( "github.com/anchore/binny/internal/log" ) +const latest = "latest" + var _ binny.VersionResolver = (*VersionResolver)(nil) type VersionResolver struct { @@ -19,7 +21,8 @@ type VersionResolver struct { } type VersionResolutionParameters struct { - Module string `json:"module" yaml:"module" mapstructure:"module"` + Module string `json:"module" yaml:"module" mapstructure:"module"` + AllowUnresolvedVersion bool `json:"allow-unresolved-version" yaml:"allow-unresolved-version" mapstructure:"allow-unresolved-version"` } func NewVersionResolver(cfg VersionResolutionParameters) *VersionResolver { @@ -35,7 +38,7 @@ func (v VersionResolver) ResolveVersion(want, _ string) (string, error) { return want, nil } - if want == "latest" { + if want == latest { return v.findLatestVersion("") } @@ -45,7 +48,7 @@ func (v VersionResolver) ResolveVersion(want, _ string) (string, error) { } func (v VersionResolver) UpdateVersion(want, constraint string) (string, error) { - if want == "latest" { + if want == latest { if constraint != "" { return "", fmt.Errorf("cannot specify a version constraint with 'latest' go module version") } @@ -75,8 +78,21 @@ func (v VersionResolver) findLatestVersion(versionConstraint string) (string, er return "", fmt.Errorf("failed to filter latest version: %v", err) } - log.WithFields("latest", latestVersion, "module", v.config.Module). - Trace("found latest version from the go proxy") + if latestVersion != "" { + log.WithFields(latest, latestVersion, "module", v.config.Module). + Trace("found latest version from the go proxy") + } else { + log.WithFields("module", v.config.Module).Trace("could not resolve latest version from go proxy") + } + + if latestVersion == "" { + if v.config.AllowUnresolvedVersion { + // this can happen if the source repo has no tags, the proxy then won't know about it. + log.WithFields("module", v.config.Module).Trace("using 'latest' as the version") + return latest, nil + } + return "", fmt.Errorf("could not resolve latest version for module %q", v.config.Module) + } return latestVersion, nil } diff --git a/tool/goproxy/version_resolver_test.go b/tool/goproxy/version_resolver_test.go index d054f61..d1c4f07 100644 --- a/tool/goproxy/version_resolver_test.go +++ b/tool/goproxy/version_resolver_test.go @@ -44,6 +44,29 @@ func TestVersionResolver_ResolveVersion(t *testing.T) { version: "bogus", want: "bogus", }, + { + name: "do not allow for unresolved versions", + config: VersionResolutionParameters{ + Module: "github.com/anchore/binny", + }, + version: "latest", + wantErr: require.Error, + availableVersionsFetcher: func(url string) ([]string, error) { + return []string{""}, nil + }, + }, + { + name: "allow for unresolved versions", + config: VersionResolutionParameters{ + Module: "github.com/anchore/binny", + AllowUnresolvedVersion: true, + }, + version: "latest", + want: "latest", // this is a pass through to go-install, which supports this as input + availableVersionsFetcher: func(url string) ([]string, error) { + return []string{""}, nil + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {