Skip to content

Commit

Permalink
feat: add support for output of older spec versions
Browse files Browse the repository at this point in the history
Signed-off-by: nscuro <nscuro@protonmail.com>
  • Loading branch information
nscuro committed Sep 28, 2022
1 parent d06405b commit df6b19e
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 13 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ FLAGS
-main ... Path to the application's main package, relative to MODULE_PATH
-noserial=false Omit serial number
-output - Output file path (or - for STDOUT)
-output-version 1.4 Output spec verson (1.4, 1.3, 1.2, 1.1, 1.0)
-packages=false Include packages
-serial ... Serial number
-std=false Include Go standard library as component and dependency of the module
Expand Down Expand Up @@ -164,6 +165,7 @@ FLAGS
-licenses=false Perform license detection
-noserial=false Omit serial number
-output - Output file path (or - for STDOUT)
-output-version 1.4 Output spec verson (1.4, 1.3, 1.2, 1.1, 1.0)
-serial ... Serial number
-std=false Include Go standard library as component and dependency of the module
-verbose=false Enable verbose output
Expand All @@ -188,6 +190,7 @@ FLAGS
-licenses=false Perform license detection
-noserial=false Omit serial number
-output - Output file path (or - for STDOUT)
-output-version 1.4 Output spec verson (1.4, 1.3, 1.2, 1.1, 1.0)
-serial ... Serial number
-std=false Include Go standard library as component and dependency of the module
-test=false Include test dependencies
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/CycloneDX/cyclonedx-gomod
go 1.18

require (
github.com/CycloneDX/cyclonedx-go v0.6.0
github.com/CycloneDX/cyclonedx-go v0.7.0
github.com/bradleyjkemp/cupaloy/v2 v2.8.0
github.com/go-enry/go-license-detector/v4 v4.3.0
github.com/go-git/go-git/v5 v5.4.2
Expand Down
5 changes: 2 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/CycloneDX/cyclonedx-go v0.6.0 h1:SizWGbZzFTC/O/1yh072XQBMxfvsoWqd//oKCIyzFyE=
github.com/CycloneDX/cyclonedx-go v0.6.0/go.mod h1:nQCiF4Tvrg5Ieu8qPhYMvzPGMu5I7fANZkrSsJjl5mg=
github.com/CycloneDX/cyclonedx-go v0.7.0 h1:jNxp8hL7UpcvPDFXjY+Y1ibFtsW+e5zyF9QoSmhK/zg=
github.com/CycloneDX/cyclonedx-go v0.7.0/go.mod h1:W5Z9w8pTTL+t+yG3PCiFRGlr8PUlE0pGWzKSJbsyXkg=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
Expand All @@ -13,7 +13,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/bradleyjkemp/cupaloy/v2 v2.7.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
Expand Down
2 changes: 2 additions & 0 deletions internal/cli/cmd/app/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"testing"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -100,6 +101,7 @@ func TestOptions_Validate(t *testing.T) {
var options Options
options.ModuleDir = tmpDir
options.Main = "cmd/app"
options.OutputVersion = cdx.SpecVersion1_4.String()

err = options.Validate()
require.NoError(t, err)
Expand Down
5 changes: 4 additions & 1 deletion internal/cli/cmd/mod/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ package mod
import (
"testing"

"github.com/CycloneDX/cyclonedx-gomod/internal/cli/options"
cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/stretchr/testify/require"

"github.com/CycloneDX/cyclonedx-gomod/internal/cli/options"
)

func TestModOptions_Validate(t *testing.T) {
t.Run("InvalidComponentType", func(t *testing.T) {
var modOptions Options
modOptions.ComponentType = "foobar"
modOptions.OutputVersion = cdx.SpecVersion1_4.String()

err := modOptions.Validate()
require.Error(t, err)
Expand Down
21 changes: 20 additions & 1 deletion internal/cli/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ import (
"flag"
"fmt"
"os"
"strings"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"

"github.com/google/uuid"

"github.com/CycloneDX/cyclonedx-gomod/internal/util"
)

// ValidationError represents a validation error for options.
Expand Down Expand Up @@ -89,16 +93,31 @@ func (l LogOptions) Validate() error {
// OutputOptions provides options for customizing the output.
type OutputOptions struct {
OutputFilePath string
OutputVersion string
UseJSON bool
}

func (o *OutputOptions) RegisterFlags(fs *flag.FlagSet) {
versionChoices := []string{
cdx.SpecVersion1_4.String(),
cdx.SpecVersion1_3.String(),
cdx.SpecVersion1_2.String(),
cdx.SpecVersion1_1.String(),
cdx.SpecVersion1_0.String(),
}

fs.BoolVar(&o.UseJSON, "json", false, "Output in JSON")
fs.StringVar(&o.OutputFilePath, "output", "-", "Output file path (or - for STDOUT)")
fs.StringVar(&o.OutputVersion, "output-version", cdx.SpecVersion1_4.String(),
fmt.Sprintf("Output spec verson (%s)", strings.Join(versionChoices, ", ")))
}

func (o OutputOptions) Validate() error {
return nil // Nothing to validate
if _, err := util.ParseSpecVersion(o.OutputVersion); err != nil {
return &ValidationError{Errors: []error{err}}
}

return nil
}

// SBOMOptions provides options for customizing the SBOM.
Expand Down
15 changes: 14 additions & 1 deletion internal/cli/options/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package options
import (
"testing"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/stretchr/testify/require"
)

Expand All @@ -33,7 +34,19 @@ func TestLogOptions_Validate(t *testing.T) {
func TestOutputOptions_Validate(t *testing.T) {
t.Run("Empty", func(t *testing.T) {
var options OutputOptions
require.NoError(t, options.Validate())

err := options.Validate()
require.Error(t, err)
require.ErrorContains(t, err, cdx.ErrInvalidSpecVersion.Error())
})

t.Run("InvalidOutputVersion", func(t *testing.T) {
var options OutputOptions
options.OutputVersion = "1.5"

err := options.Validate()
require.Error(t, err)
require.ErrorContains(t, err, cdx.ErrInvalidSpecVersion.Error())
})
}

Expand Down
8 changes: 7 additions & 1 deletion internal/cli/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/CycloneDX/cyclonedx-gomod/internal/cli/options"
"github.com/CycloneDX/cyclonedx-gomod/internal/sbom"
"github.com/CycloneDX/cyclonedx-gomod/internal/util"
)

func AddCommonMetadata(logger zerolog.Logger, bom *cdx.BOM) error {
Expand Down Expand Up @@ -75,6 +76,11 @@ func WriteBOM(bom *cdx.BOM, outputOptions options.OutputOptions) error {
outputFormat = cdx.BOMFileFormatXML
}

outputVersion, err := util.ParseSpecVersion(outputOptions.OutputVersion)
if err != nil {
return fmt.Errorf("failed to parse output version: %w", err)
}

var outputWriter io.Writer
if outputOptions.OutputFilePath == "" || outputOptions.OutputFilePath == "-" {
outputWriter = os.Stdout
Expand All @@ -90,7 +96,7 @@ func WriteBOM(bom *cdx.BOM, outputOptions options.OutputOptions) error {
encoder := cdx.NewBOMEncoder(outputWriter, outputFormat)
encoder.SetPretty(true)

if err := encoder.Encode(bom); err != nil {
if err := encoder.EncodeVersion(bom, outputVersion); err != nil {
return fmt.Errorf("failed to encode sbom: %w", err)
}

Expand Down
6 changes: 3 additions & 3 deletions internal/sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ func BuildDependencyGraph(modules []gomod.Module) []cdx.Dependency {
cdxDependant := cdx.Dependency{Ref: module.PackageURL()}

if module.Dependencies != nil {
cdxDependencies := make([]cdx.Dependency, len(module.Dependencies))
cdxDependencies := make([]string, len(module.Dependencies))
for i := range module.Dependencies {
if module.Dependencies[i].Replace != nil {
cdxDependencies[i] = cdx.Dependency{Ref: module.Dependencies[i].Replace.PackageURL()}
cdxDependencies[i] = module.Dependencies[i].Replace.PackageURL()
} else {
cdxDependencies[i] = cdx.Dependency{Ref: module.Dependencies[i].PackageURL()}
cdxDependencies[i] = module.Dependencies[i].PackageURL()
}
}
if len(cdxDependencies) > 0 {
Expand Down
4 changes: 2 additions & 2 deletions internal/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ func RequireStdlibComponentToBeRedacted(t *testing.T, bom *cdx.BOM, expectPackag
(*bom.Dependencies)[i].Ref = newPURL
} else if dependency.Dependencies != nil { // Dependencies
for j, dependency2 := range *(*bom.Dependencies)[i].Dependencies {
if dependency2.Ref == oldPURL {
(*(*bom.Dependencies)[i].Dependencies)[j].Ref = newPURL
if dependency2 == oldPURL {
(*(*bom.Dependencies)[i].Dependencies)[j] = newPURL
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions internal/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"os"
"path/filepath"
"strings"

cdx "github.com/CycloneDX/cyclonedx-go"
)

func FileExists(path string) bool {
Expand All @@ -47,3 +49,22 @@ func IsSubPath(subject, path string) (bool, error) {

return true, nil
}

func ParseSpecVersion(specVersion string) (sv cdx.SpecVersion, err error) {
switch specVersion {
case cdx.SpecVersion1_0.String():
sv = cdx.SpecVersion1_0
case cdx.SpecVersion1_1.String():
sv = cdx.SpecVersion1_1
case cdx.SpecVersion1_2.String():
sv = cdx.SpecVersion1_2
case cdx.SpecVersion1_3.String():
sv = cdx.SpecVersion1_3
case cdx.SpecVersion1_4.String():
sv = cdx.SpecVersion1_4
default:
err = cdx.ErrInvalidSpecVersion
}

return
}

0 comments on commit df6b19e

Please sign in to comment.