accept main.version ldflags even without vcs (#1855)

Signed-off-by: Avi Deitcher <avi@deitcher.net>
This commit is contained in:
Avi Deitcher 2023-06-01 15:34:46 +03:00 committed by GitHub
parent c69cdd9f4a
commit 68f8df9594
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 153 additions and 27 deletions

View File

@ -85,35 +85,32 @@ func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *debug
version, hasVersion := gbs["vcs.revision"] version, hasVersion := gbs["vcs.revision"]
timestamp, hasTimestamp := gbs["vcs.time"] timestamp, hasTimestamp := gbs["vcs.time"]
if hasVersion { var ldflags string
if hasTimestamp { if metadata, ok := main.Metadata.(pkg.GolangBinMetadata); ok {
//NOTE: err is ignored, because if parsing fails // we've found a specific version from the ldflags! use it as the version.
// we still use the empty Time{} struct to generate an empty date, like 00010101000000 // why not combine that with the pseudo version (e.g. v1.2.3-0.20210101000000-abcdef123456)?
// for consistency with the pseudo-version format: https://go.dev/ref/mod#pseudo-versions // short answer: we're assuming that if a specific semver was provided in the ldflags that
ts, _ := time.Parse(time.RFC3339, timestamp) // there is a matching vcs tag to match that could be referenced. This assumption could
if len(version) >= 12 { // be incorrect in terms of the go.mod contents, but is not incorrect in terms of the logical
version = version[:12] // version of the package.
} ldflags = metadata.BuildSettings["-ldflags"]
}
var ldflags string majorVersion, fullVersion := extractVersionFromLDFlags(ldflags)
if metadata, ok := main.Metadata.(pkg.GolangBinMetadata); ok { if fullVersion != "" {
ldflags = metadata.BuildSettings["-ldflags"] version = fullVersion
} } else if hasVersion && hasTimestamp {
//NOTE: err is ignored, because if parsing fails
majorVersion, fullVersion := extractVersionFromLDFlags(ldflags) // we still use the empty Time{} struct to generate an empty date, like 00010101000000
if fullVersion != "" { // for consistency with the pseudo-version format: https://go.dev/ref/mod#pseudo-versions
// we've found a specific version from the ldflags! use it as the version. ts, _ := time.Parse(time.RFC3339, timestamp)
// why not combine that with the pseudo version (e.g. v1.2.3-0.20210101000000-abcdef123456)? if len(version) >= 12 {
// short answer: we're assuming that if a specific semver was provided in the ldflags that version = version[:12]
// there is a matching vcs tag to match that could be referenced. This assumption could
// be incorrect in terms of the go.mod contents, but is not incorrect in terms of the logical
// version of the package.
version = fullVersion
} else {
version = module.PseudoVersion(majorVersion, fullVersion, ts, version)
}
} }
version = module.PseudoVersion(majorVersion, fullVersion, ts, version)
}
if version != "" {
main.Version = version main.Version = version
main.PURL = packageURL(main.Name, main.Version) main.PURL = packageURL(main.Name, main.Version)

View File

@ -347,7 +347,7 @@ func TestBuildGoPkgInfo(t *testing.T) {
}, },
}, },
{ {
name: "parse main mod and replace devel version with one from ldflags", name: "parse main mod and replace devel version with one from ldflags with vcs. build settings",
arch: archDetails, arch: archDetails,
mod: &debug.BuildInfo{ mod: &debug.BuildInfo{
GoVersion: goCompiledVersion, GoVersion: goCompiledVersion,
@ -393,6 +393,135 @@ func TestBuildGoPkgInfo(t *testing.T) {
}, },
}, },
}, },
{
name: "parse main mod and replace devel version with one from ldflags without any vcs. build settings",
arch: archDetails,
mod: &debug.BuildInfo{
GoVersion: goCompiledVersion,
Main: debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
Settings: []debug.BuildSetting{
{Key: "GOARCH", Value: archDetails},
{Key: "GOOS", Value: "darwin"},
{Key: "GOAMD64", Value: "v1"},
{Key: "-ldflags", Value: `build -ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`},
},
},
expected: []pkg.Package{
{
Name: "github.com/anchore/syft",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Version: "v0.79.0",
PURL: "pkg:golang/github.com/anchore/syft@v0.79.0",
Locations: file.NewLocationSet(
file.NewLocationFromCoordinates(
file.Coordinates{
RealPath: "/a-path",
FileSystemID: "layer-id",
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
MetadataType: pkg.GolangBinMetadataType,
Metadata: pkg.GolangBinMetadata{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
BuildSettings: map[string]string{
"GOARCH": archDetails,
"GOOS": "darwin",
"GOAMD64": "v1",
"-ldflags": `build -ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`,
},
MainModule: "github.com/anchore/syft",
},
},
},
},
{
name: "parse main mod and replace devel version with one from ldflags main.version without any vcs. build settings",
arch: archDetails,
mod: &debug.BuildInfo{
GoVersion: goCompiledVersion,
Main: debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
Settings: []debug.BuildSetting{
{Key: "GOARCH", Value: archDetails},
{Key: "GOOS", Value: "darwin"},
{Key: "GOAMD64", Value: "v1"},
{Key: "-ldflags", Value: `build -ldflags="-w -s -extldflags '-static' -X main.version=0.79.0`},
},
},
expected: []pkg.Package{
{
Name: "github.com/anchore/syft",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Version: "v0.79.0",
PURL: "pkg:golang/github.com/anchore/syft@v0.79.0",
Locations: file.NewLocationSet(
file.NewLocationFromCoordinates(
file.Coordinates{
RealPath: "/a-path",
FileSystemID: "layer-id",
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
MetadataType: pkg.GolangBinMetadataType,
Metadata: pkg.GolangBinMetadata{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
BuildSettings: map[string]string{
"GOARCH": archDetails,
"GOOS": "darwin",
"GOAMD64": "v1",
"-ldflags": `build -ldflags="-w -s -extldflags '-static' -X main.version=0.79.0`,
},
MainModule: "github.com/anchore/syft",
},
},
},
},
{
name: "parse main mod and replace devel version with one from ldflags main.Version without any vcs. build settings",
arch: archDetails,
mod: &debug.BuildInfo{
GoVersion: goCompiledVersion,
Main: debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
Settings: []debug.BuildSetting{
{Key: "GOARCH", Value: archDetails},
{Key: "GOOS", Value: "darwin"},
{Key: "GOAMD64", Value: "v1"},
{Key: "-ldflags", Value: `build -ldflags="-w -s -extldflags '-static' -X main.Version=0.79.0`},
},
},
expected: []pkg.Package{
{
Name: "github.com/anchore/syft",
Language: pkg.Go,
Type: pkg.GoModulePkg,
Version: "v0.79.0",
PURL: "pkg:golang/github.com/anchore/syft@v0.79.0",
Locations: file.NewLocationSet(
file.NewLocationFromCoordinates(
file.Coordinates{
RealPath: "/a-path",
FileSystemID: "layer-id",
},
).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
MetadataType: pkg.GolangBinMetadataType,
Metadata: pkg.GolangBinMetadata{
GoCompiledVersion: goCompiledVersion,
Architecture: archDetails,
BuildSettings: map[string]string{
"GOARCH": archDetails,
"GOOS": "darwin",
"GOAMD64": "v1",
"-ldflags": `build -ldflags="-w -s -extldflags '-static' -X main.Version=0.79.0`,
},
MainModule: "github.com/anchore/syft",
},
},
},
},
{ {
name: "parse main mod and replace devel version with a pseudo version", name: "parse main mod and replace devel version with a pseudo version",
arch: archDetails, arch: archDetails,