skipped 298 lines 299 299 expected: []pkg.Package{unmodifiedMain}, 300 300 }, 301 301 { 302 - name: "parse main mod and replace devel version", 302 + name: "parse main mod and replace devel pseudo version and ldflags exists ( but contains no version ) ", 303 + arch: archDetails, 304 + mod: &debug.BuildInfo{ 305 + GoVersion: goCompiledVersion, 306 + Main: debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"}, 307 + Settings: []debug.BuildSetting{ 308 + {Key: "GOARCH", Value: archDetails}, 309 + {Key: "GOOS", Value: "darwin"}, 310 + {Key: "GOAMD64", Value: "v1"}, 311 + {Key: "vcs.revision", Value: "41bc6bb410352845f22766e27dd48ba93aa825a4"}, 312 + {Key: "vcs.time", Value: "2022-10-14T19:54:57Z"}, 313 + {Key: "-ldflags", Value: `build -ldflags="-w -s -extldflags '-static' -X blah=foobar`}, 314 + }, 315 + }, 316 + expected: []pkg.Package{ 317 + { 318 + Name: "github.com/anchore/syft", 319 + Language: pkg.Go, 320 + Type: pkg.GoModulePkg, 321 + Version: "v0.0.0-20221014195457-41bc6bb41035", 322 + PURL: "pkg:golang/github.com/anchore/[email protected] ", 323 + Locations: source.NewLocationSet( 324 + source.NewLocationFromCoordinates( 325 + source.Coordinates{ 326 + RealPath: "/a-path", 327 + FileSystemID: "layer-id", 328 + }, 329 + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), 330 + ), 331 + MetadataType: pkg.GolangBinMetadataType, 332 + Metadata: pkg.GolangBinMetadata{ 333 + GoCompiledVersion: goCompiledVersion, 334 + Architecture: archDetails, 335 + BuildSettings: map[string]string{ 336 + "GOARCH": archDetails, 337 + "GOOS": "darwin", 338 + "GOAMD64": "v1", 339 + "vcs.revision": "41bc6bb410352845f22766e27dd48ba93aa825a4", 340 + "vcs.time": "2022-10-14T19:54:57Z", 341 + "-ldflags": `build -ldflags="-w -s -extldflags '-static' -X blah=foobar`, 342 + }, 343 + MainModule: "github.com/anchore/syft", 344 + }, 345 + }, 346 + }, 347 + }, 348 + { 349 + name: "parse main mod and replace devel version with one from ldflags", 350 + arch: archDetails, 351 + mod: &debug.BuildInfo{ 352 + GoVersion: goCompiledVersion, 353 + Main: debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"}, 354 + Settings: []debug.BuildSetting{ 355 + {Key: "GOARCH", Value: archDetails}, 356 + {Key: "GOOS", Value: "darwin"}, 357 + {Key: "GOAMD64", Value: "v1"}, 358 + {Key: "vcs.revision", Value: "41bc6bb410352845f22766e27dd48ba93aa825a4"}, 359 + {Key: "vcs.time", Value: "2022-10-14T19:54:57Z"}, 360 + {Key: "-ldflags", Value: `build -ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`}, 361 + }, 362 + }, 363 + expected: []pkg.Package{ 364 + { 365 + Name: "github.com/anchore/syft", 366 + Language: pkg.Go, 367 + Type: pkg.GoModulePkg, 368 + Version: "v0.79.0", 369 + PURL: "pkg:golang/github.com/anchore/[email protected] ", 370 + Locations: source.NewLocationSet( 371 + source.NewLocationFromCoordinates( 372 + source.Coordinates{ 373 + RealPath: "/a-path", 374 + FileSystemID: "layer-id", 375 + }, 376 + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), 377 + ), 378 + MetadataType: pkg.GolangBinMetadataType, 379 + Metadata: pkg.GolangBinMetadata{ 380 + GoCompiledVersion: goCompiledVersion, 381 + Architecture: archDetails, 382 + BuildSettings: map[string]string{ 383 + "GOARCH": archDetails, 384 + "GOOS": "darwin", 385 + "GOAMD64": "v1", 386 + "vcs.revision": "41bc6bb410352845f22766e27dd48ba93aa825a4", 387 + "vcs.time": "2022-10-14T19:54:57Z", 388 + "-ldflags": `build -ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`, 389 + }, 390 + MainModule: "github.com/anchore/syft", 391 + }, 392 + }, 393 + }, 394 + }, 395 + { 396 + name: "parse main mod and replace devel version with a pseudo version", 303 397 arch: archDetails, 304 398 mod: &debug.BuildInfo{ 305 399 GoVersion: goCompiledVersion, skipped 207 lines 513 607 } 514 608 } 515 609 610 + func Test_extractVersionFromLDFlags(t *testing.T) { 611 + tests := []struct { 612 + name string 613 + ldflags string 614 + wantMajorVersion string 615 + wantFullVersion string 616 + }{ 617 + { 618 + name: "empty ldflags", 619 + ldflags: "", 620 + }, 621 + { 622 + name: "syft ldflags", 623 + ldflags: ` build -ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0 -X github.com/anchore/syft/internal/version.gitCommit=b2b332e8b2b66af0905e98b54ebd713a922be1a8 -X github.com/anchore/syft/internal/version.buildDate=2023-04-21T16:20:25Z -X github.com/anchore/syft/internal/version.gitDescription=v0.79.0 "`, 624 + wantMajorVersion: "0", 625 + wantFullVersion: "v0.79.0", 626 + }, 627 + { 628 + name: "kubectl ldflags", 629 + ldflags: ` build -asmflags=all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes 630 + build -compiler=gc 631 + build -gcflags="all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes " 632 + build -ldflags="all=-X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/client-go/pkg/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/component-base/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/client-go/pkg/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/component-base/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitVersion=v1.25.9' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitVersion=v1.25.9' -X 'k8s.io/client-go/pkg/version.gitVersion=v1.25.9' -X 'k8s.io/component-base/version.gitVersion=v1.25.9' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMinor=25' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMinor=25' -X 'k8s.io/client-go/pkg/version.gitMinor=25' -X 'k8s.io/component-base/version.gitMinor=25' -s -w"`, 633 + wantMajorVersion: "1", 634 + wantFullVersion: "v1.25.9", 635 + }, 636 + { 637 + name: "nerdctl ldflags", 638 + ldflags: ` build -ldflags="-s -w -X github.com/containerd/nerdctl/pkg/version.Version=v1.3.1 -X github.com/containerd/nerdctl/pkg/version.Revision=b224b280ff3086516763c7335fc0e0997aca617a"`, 639 + wantMajorVersion: "1", 640 + wantFullVersion: "v1.3.1", 641 + }, 642 + { 643 + name: "limactl ldflags", 644 + ldflags: ` build -ldflags="-s -w -X github.com/lima-vm/lima/pkg/version.Version=v0.15.1"`, 645 + wantMajorVersion: "0", 646 + wantFullVersion: "v0.15.1", 647 + }, 648 + { 649 + name: "terraform ldflags", 650 + ldflags: ` build -ldflags="-w -s -X 'github.com/hashicorp/terraform/version.Version=1.4.6' -X 'github.com/hashicorp/terraform/version.Prerelease='"`, 651 + wantMajorVersion: "1", 652 + wantFullVersion: "v1.4.6", 653 + }, 654 + { 655 + name: "kube-apiserver ldflags", 656 + ldflags: ` build -asmflags=all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes 657 + build -buildmode=exe 658 + build -compiler=gc 659 + build -gcflags="all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes " 660 + build -ldflags="all=-X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/client-go/pkg/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/component-base/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/client-go/pkg/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/component-base/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitVersion=v1.27.1' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitVersion=v1.27.1' -X 'k8s.io/client-go/pkg/version.gitVersion=v1.27.1' -X 'k8s.io/component-base/version.gitVersion=v1.27.1' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMinor=27' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMinor=27' -X 'k8s.io/client-go/pkg/version.gitMinor=27' -X 'k8s.io/component-base/version.gitMinor=27' -s -w"`, 661 + wantMajorVersion: "1", 662 + wantFullVersion: "v1.27.1", 663 + }, 664 + { 665 + name: "prometheus ldflags", 666 + ldflags: ` build -ldflags="-X github.com/prometheus/common/version.Version=2.44.0 -X github.com/prometheus/common/version.Revision=1ac5131f698ebc60f13fe2727f89b115a41f6558 -X github.com/prometheus/common/version.Branch=HEAD -X github.com/prometheus/common/version.BuildUser=root@739e8181c5db -X github.com/prometheus/common/version.BuildDate=20230514-06:18:11 -extldflags '-static'" 667 + build -tags=netgo,builtinassets,stringlabels`, 668 + wantMajorVersion: "2", 669 + wantFullVersion: "v2.44.0", 670 + }, 671 + { 672 + name: "influxdb ldflags", 673 + ldflags: ` build -ldflags="-s -w -X main.version=v2.7.1 -X main.commit=407fa622e9 -X main.date=2023-04-28T13:24:27Z -linkmode=external -extld=/musl/x86_64/bin/musl-gcc -extldflags '-fno-PIC -static-pie -Wl,-z,stack-size=8388608'" 674 + build -tags=assets,sqlite_foreign_keys,sqlite_json,static_build,noasm`, 675 + wantMajorVersion: "2", 676 + wantFullVersion: "v2.7.1", 677 + }, 678 + { 679 + name: "gitea ldflags", 680 + ldflags: ` build -ldflags=" -X \"main.MakeVersion=GNU Make 4.1\" -X \"main.Version=1.19.3\" -X \"main.Tags=bindata sqlite sqlite_unlock_notify\" "`, 681 + wantMajorVersion: "1", 682 + wantFullVersion: "v1.19.3", 683 + }, 684 + { 685 + name: "docker sbom cli ldflags", 686 + ldflags: ` build -ldflags="-w -s -extldflags '-static' -X github.com/docker/sbom-cli-plugin/internal/version.version=0.6.1-SNAPSHOT-02cf1c8 -X github.com/docker/sbom-cli-plugin/internal/version.gitCommit=02cf1c888ad6662109ac6e3be618392514a56316 -X github.com/docker/sbom-cli-plugin/internal/version.gitDescription=v0.6.1-dirty "`, 687 + wantMajorVersion: "0", 688 + wantFullVersion: "v0.6.1-SNAPSHOT-02cf1c8", 689 + }, 690 + { 691 + name: "docker scout ldflags", 692 + ldflags: ` build -ldflags="-w -s -extldflags '-static' -X github.com/docker/scout-cli-plugin/internal.version=0.10.0 "`, 693 + wantMajorVersion: "0", 694 + wantFullVersion: "v0.10.0", 695 + }, 696 + { 697 + name: "influx telegraf ldflags", 698 + ldflags: ` build -ldflags="-w -s -X github.com/influxdata/telegraf/internal.Commit=a3a884a1 -X github.com/influxdata/telegraf/internal.Branch=HEAD -X github.com/influxdata/telegraf/internal.Version=1.26.2"`, 699 + wantMajorVersion: "1", 700 + wantFullVersion: "v1.26.2", 701 + }, 702 + { 703 + name: "argocd ldflags", 704 + ldflags: ` build -ldflags="-X github.com/argoproj/argo-cd/v2/common.version=2.7.2 -X github.com/argoproj/argo-cd/v2/common.buildDate=2023-05-12T14:06:49Z -X github.com/argoproj/argo-cd/v2/common.gitCommit=cbee7e6011407ed2d1066c482db74e97e0cc6bdb -X github.com/argoproj/argo-cd/v2/common.gitTreeState=clean -X github.com/argoproj/argo-cd/v2/common.kubectlVersion=v0.24.2 -extldflags=\"-static\""`, 705 + wantMajorVersion: "2", 706 + wantFullVersion: "v2.7.2", 707 + }, 708 + { 709 + name: "kustomize ldflags", 710 + ldflags: ` build -ldflags="-s -X sigs.k8s.io/kustomize/api/provenance.version=kustomize/v4.5.7 -X sigs.k8s.io/kustomize/api/provenance.gitCommit=56d82a8378dfc8dc3b3b1085e5a6e67b82966bd7 -X sigs.k8s.io/kustomize/api/provenance.buildDate=2022-08-02T16:35:54Z "`, 711 + wantMajorVersion: "4", 712 + wantFullVersion: "v4.5.7", 713 + }, 714 + ////////////////////////////////////////////////////////////////// 715 + // negative cases 716 + { 717 + name: "hugo ldflags", 718 + ldflags: ` build -ldflags="-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio"`, 719 + }, 720 + { 721 + name: "ghostunnel ldflags", 722 + ldflags: ` build -ldflags="-X main.version=77d9aaa"`, 723 + }, 724 + { 725 + name: "opa ldflags", 726 + ldflags: `build -ldflags=" -X github.com/open-policy-agent/opa/version.Hostname=9549178459bc"`, 727 + }, 728 + /////////////////////////////////////////////////////////////////// 729 + // trickier cases 730 + { 731 + name: "macvlan plugin for cri-o ldflags", 732 + ldflags: ` build -ldflags="-extldflags -static -X github.com/containernetworking/plugins/pkg/utils/buildversion.BuildVersion=v1.2.0"`, 733 + wantMajorVersion: "1", 734 + wantFullVersion: "v1.2.0", 735 + }, 736 + { 737 + name: "coder ldflags", 738 + ldflags: ` build -ldflags="-s -w -X 'github.com/coder/coder/buildinfo.tag=0.23.4'"`, 739 + wantMajorVersion: "0", 740 + wantFullVersion: "v0.23.4", 741 + }, 742 + /////////////////////////////////////////////////////////////////// 743 + // don't know how to handle these... yet 744 + //{ 745 + // // package name: pkgName: "github.com/krakendio/krakend-ce/v2", 746 + // name: "krakenD ldflags", 747 + // ldflags: ` build -ldflags="-X github.com/luraproject/lura/v2/core.KrakendVersion=2.3.2 -X github.com/luraproject/lura/v2/core.GoVersion=1.20.4 -X github.com/luraproject/lura/v2/core.GlibcVersion=GLIBC-2.31_(debian-11) "`, 748 + // wantMajorVersion: "2.3.2", 749 + // wantFullVersion: "v2.3.2", 750 + //}, 751 + //{ 752 + // // package name: pkgName: "github.com/krakendio/krakend-ce/v2", 753 + // name: "krakenD ldflags -- answer embedded in the middle", 754 + // ldflags: ` build -ldflags=" -X github.com/luraproject/lura/v2/core.GoVersion=1.20.4 -X github.com/luraproject/lura/v2/core.KrakendVersion=2.3.2 -X github.com/luraproject/lura/v2/core.GlibcVersion=GLIBC-2.31_(debian-11) "`, 755 + // wantMajorVersion: "2.3.2", 756 + // wantFullVersion: "v2.3.2", 757 + //}, 758 + } 759 + for _, tt := range tests { 760 + t.Run(tt.name, func(t *testing.T) { 761 + gotMajorVersion, gotFullVersion := extractVersionFromLDFlags(tt.ldflags) 762 + assert.Equal(t, tt.wantMajorVersion, gotMajorVersion, "unexpected major version") 763 + assert.Equal(t, tt.wantFullVersion, gotFullVersion, "unexpected full version") 764 + }) 765 + } 766 + } 767 +