Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

accept main.version ldflags even without vcs #1855

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 24 additions & 27 deletions syft/pkg/cataloger/golang/parse_go_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,35 +85,32 @@ func (c *goBinaryCataloger) makeGoMainPackage(resolver file.Resolver, mod *debug
version, hasVersion := gbs["vcs.revision"]
timestamp, hasTimestamp := gbs["vcs.time"]

if hasVersion {
if hasTimestamp {
//NOTE: err is ignored, because if parsing fails
// we still use the empty Time{} struct to generate an empty date, like 00010101000000
// for consistency with the pseudo-version format: https://go.dev/ref/mod#pseudo-versions
ts, _ := time.Parse(time.RFC3339, timestamp)
if len(version) >= 12 {
version = version[:12]
}

var ldflags string
if metadata, ok := main.Metadata.(pkg.GolangBinMetadata); ok {
ldflags = metadata.BuildSettings["-ldflags"]
}

majorVersion, fullVersion := extractVersionFromLDFlags(ldflags)
if fullVersion != "" {
// we've found a specific version from the ldflags! use it as the version.
// why not combine that with the pseudo version (e.g. v1.2.3-0.20210101000000-abcdef123456)?
// short answer: we're assuming that if a specific semver was provided in the ldflags that
// 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)
}
var ldflags string
if metadata, ok := main.Metadata.(pkg.GolangBinMetadata); ok {
// we've found a specific version from the ldflags! use it as the version.
// why not combine that with the pseudo version (e.g. v1.2.3-0.20210101000000-abcdef123456)?
// short answer: we're assuming that if a specific semver was provided in the ldflags that
// 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.
ldflags = metadata.BuildSettings["-ldflags"]
}

majorVersion, fullVersion := extractVersionFromLDFlags(ldflags)
if fullVersion != "" {
version = fullVersion
} else if hasVersion && hasTimestamp {
//NOTE: err is ignored, because if parsing fails
// we still use the empty Time{} struct to generate an empty date, like 00010101000000
// for consistency with the pseudo-version format: https://go.dev/ref/mod#pseudo-versions
ts, _ := time.Parse(time.RFC3339, timestamp)
if len(version) >= 12 {
version = version[:12]
}

version = module.PseudoVersion(majorVersion, fullVersion, ts, version)
}
if version != "" {
main.Version = version
main.PURL = packageURL(main.Name, main.Version)

Expand Down
131 changes: 130 additions & 1 deletion syft/pkg/cataloger/golang/parse_go_binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
mod: &debug.BuildInfo{
GoVersion: goCompiledVersion,
Expand Down Expand Up @@ -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",
arch: archDetails,
Expand Down