Skip to content

Commit

Permalink
Merge pull request #18 from LucasVanHaaren/main
Browse files Browse the repository at this point in the history
Add parent project support
  • Loading branch information
takumakume authored Sep 7, 2024
2 parents 5429cea + 9886b91 commit 473076c
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 10 deletions.
6 changes: 6 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Dependency-Track APK key permissions required:
viper.GetString("project-name"),
viper.GetString("project-version"),
viper.GetStringSlice("project-tags"),
viper.GetString("parent-name"),
viper.GetString("parent-version"),
viper.GetFloat64("dtrack-client-timeout"),
viper.GetFloat64("sbom-upload-timeout-sec"),
viper.GetFloat64("sbom-upload-check-interval-sec"),
Expand Down Expand Up @@ -103,6 +105,8 @@ func init() {
flags.StringP("project-name", "", "[[.sbomReport.report.artifact.repository]]", "Project name template (env: DT_PROJECT_NAME)")
flags.StringP("project-version", "", "[[.sbomReport.report.artifact.tag]]", "Project version template (env: DT_PROJECT_VERSION)")
flags.StringSliceP("project-tags", "t", []string{}, "Project tags template (env: DT_PROJECT_TAGS (comma separated))")
flags.StringP("parent-name", "", "", "Parent project name template (env: DT_PARENT_PROJECT_NAME)")
flags.StringP("parent-version", "", "", "Parent project version template (env: DT_PARENT_PROJECT_VERSION)")
flags.Float64P("dtrack-client-timeout", "", 10, "Dependency Track client timeout seconds")
flags.Float64P("sbom-upload-timeout-sec", "", 30, "Seconds to timeout waiting for completion of SBOM upload of Dependency Track")
flags.Float64P("sbom-upload-check-interval-sec", "", 1, "Interval seconds to check for completion of SBOM upload of Dependency Track")
Expand All @@ -112,6 +116,8 @@ func init() {
viper.BindPFlag("project-name", flags.Lookup("project-name"))
viper.BindPFlag("project-version", flags.Lookup("project-version"))
viper.BindPFlag("project-tags", flags.Lookup("project-tags"))
viper.BindPFlag("parent-name", flags.Lookup("parent-name"))
viper.BindPFlag("parent-version", flags.Lookup("parent-version"))
viper.BindPFlag("dtrack-client-timeout", flags.Lookup("dtrack-client-timeout"))
viper.BindPFlag("sbom-upload-timeout-sec", flags.Lookup("sbom-upload-timeout-sec"))
viper.BindPFlag("sbom-upload-check-interval-sec", flags.Lookup("sbom-upload-check-interval-sec"))
Expand Down
2 changes: 2 additions & 0 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ var serverCmd = &cobra.Command{
viper.GetString("project-name"),
viper.GetString("project-version"),
viper.GetStringSlice("project-tags"),
viper.GetString("parent-name"),
viper.GetString("parent-version"),
viper.GetFloat64("dtrack-client-timeout-sec"),
viper.GetFloat64("sbom-upload-timeout-sec"),
viper.GetFloat64("sbom-upload-check-interval-sec"),
Expand Down
7 changes: 6 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ type Config struct {
ProjectVersion string
ProjectTags []string

ParentName string `json:"parentName,omitempty"`
ParentVersion string `json:"parentVersion,omitempty"`

DtrackClientTimeout time.Duration
SBOMUploadTimeout time.Duration
SBOMUploadCheckInterval time.Duration
}

var ErrAPIKeyIsRequired = errors.New("api-key is required")

func New(baseURL, apiKey, projectName, projectVersion string, projectTags []string, dtrackClientTimeoutSec, sbomUploadTimeoutSec, sbomUploadCheckIntervalSec float64) *Config {
func New(baseURL, apiKey, projectName, projectVersion string, projectTags []string, parentName string, parentVersion string, dtrackClientTimeoutSec, sbomUploadTimeoutSec, sbomUploadCheckIntervalSec float64) *Config {
if len(projectTags) == 1 && strings.Contains(projectTags[0], ",") {
projectTags = strings.Split(projectTags[0], ",")
}
Expand All @@ -32,6 +35,8 @@ func New(baseURL, apiKey, projectName, projectVersion string, projectTags []stri
ProjectName: projectName,
ProjectVersion: projectVersion,
ProjectTags: projectTags,
ParentName: parentName,
ParentVersion: parentVersion,
DtrackClientTimeout: time.Duration(dtrackClientTimeoutSec) * time.Second,
SBOMUploadTimeout: time.Duration(sbomUploadTimeoutSec) * time.Second,
SBOMUploadCheckInterval: time.Duration(sbomUploadCheckIntervalSec) * time.Second,
Expand Down
20 changes: 19 additions & 1 deletion config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ func TestNew(t *testing.T) {
projectName string
projectVersion string
projectTags []string
parentName string
parentVersion string
dtrackClientTimeoutSec float64
sbomUploadTimeoutSec float64
sbomUploadCheckIntervalSec float64
Expand All @@ -30,6 +32,8 @@ func TestNew(t *testing.T) {
projectName: "test-project",
projectVersion: "1.0.0",
projectTags: []string{"tag1", "tag2"},
parentName: "TEST",
parentVersion: "1.0.0",
dtrackClientTimeoutSec: 10,
sbomUploadTimeoutSec: 30,
sbomUploadCheckIntervalSec: 1,
Expand All @@ -40,6 +44,8 @@ func TestNew(t *testing.T) {
ProjectName: "test-project",
ProjectVersion: "1.0.0",
ProjectTags: []string{"tag1", "tag2"},
ParentName: "TEST",
ParentVersion: "1.0.0",
DtrackClientTimeout: time.Duration(10) * time.Second,
SBOMUploadTimeout: time.Duration(30) * time.Second,
SBOMUploadCheckInterval: time.Duration(1) * time.Second,
Expand All @@ -53,6 +59,8 @@ func TestNew(t *testing.T) {
projectName: "test-project",
projectVersion: "1.0.0",
projectTags: []string{"tag1,tag2"},
parentName: "TEST",
parentVersion: "1.0.0",
dtrackClientTimeoutSec: 10,
sbomUploadTimeoutSec: 30,
sbomUploadCheckIntervalSec: 1,
Expand All @@ -63,6 +71,8 @@ func TestNew(t *testing.T) {
ProjectName: "test-project",
ProjectVersion: "1.0.0",
ProjectTags: []string{"tag1", "tag2"},
ParentName: "TEST",
ParentVersion: "1.0.0",
DtrackClientTimeout: time.Duration(10) * time.Second,
SBOMUploadTimeout: time.Duration(30) * time.Second,
SBOMUploadCheckInterval: time.Duration(1) * time.Second,
Expand All @@ -71,7 +81,7 @@ func TestNew(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := New(tt.args.baseURL, tt.args.apiKey, tt.args.projectName, tt.args.projectVersion, tt.args.projectTags, tt.args.dtrackClientTimeoutSec, tt.args.sbomUploadTimeoutSec, tt.args.sbomUploadCheckIntervalSec); !reflect.DeepEqual(got, tt.want) {
if got := New(tt.args.baseURL, tt.args.apiKey, tt.args.projectName, tt.args.projectVersion, tt.args.projectTags, tt.args.parentName, tt.args.parentVersion, tt.args.dtrackClientTimeoutSec, tt.args.sbomUploadTimeoutSec, tt.args.sbomUploadCheckIntervalSec); !reflect.DeepEqual(got, tt.want) {
t.Errorf("New() = %v, want %v", got, tt.want)
}
})
Expand All @@ -85,6 +95,8 @@ func TestConfig_Validate(t *testing.T) {
ProjectName string
ProjectVersion string
ProjectTags []string
ParentName string `json:"parentName,omitempty"`
ParentVersion string `json:"parentVersion,omitempty"`
}
tests := []struct {
name string
Expand All @@ -99,6 +111,8 @@ func TestConfig_Validate(t *testing.T) {
ProjectName: "test-project",
ProjectVersion: "1.0.0",
ProjectTags: []string{"tag1", "tag2"},
ParentName: "TEST",
ParentVersion: "1.0.0",
},
wantErr: false,
},
Expand All @@ -109,6 +123,8 @@ func TestConfig_Validate(t *testing.T) {
ProjectName: "test-project",
ProjectVersion: "1.0.0",
ProjectTags: []string{"tag1", "tag2"},
ParentName: "TEST",
ParentVersion: "1.0.0",
},
wantErr: true,
},
Expand All @@ -121,6 +137,8 @@ func TestConfig_Validate(t *testing.T) {
ProjectName: tt.fields.ProjectName,
ProjectVersion: tt.fields.ProjectVersion,
ProjectTags: tt.fields.ProjectTags,
ParentName: tt.fields.ParentName,
ParentVersion: tt.fields.ParentVersion,
}
if err := c.Validate(); (err != nil) != tt.wantErr {
t.Errorf("Config.Validate() error = %v, wantErr %v", err, tt.wantErr)
Expand Down
6 changes: 4 additions & 2 deletions dependencytrack/dependencytrack.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

type DependencyTrackClient interface {
UploadBOM(ctx context.Context, projectName, projectVersion string, bom []byte) error
UploadBOM(ctx context.Context, projectName, projectVersion string, parentName string, parentVersion string, bom []byte) error
AddTagsToProject(ctx context.Context, projectName, projectVersion string, tags []string) error
}

Expand All @@ -35,12 +35,14 @@ func New(baseURL, apiKey string, dtrackClientTimeout, sbomUploadTimeout, sbomUpl
}, nil
}

func (dt *DependencyTrack) UploadBOM(ctx context.Context, projectName, projectVersion string, bom []byte) error {
func (dt *DependencyTrack) UploadBOM(ctx context.Context, projectName, projectVersion string, parentName string, parentVersion string, bom []byte) error {
log.Printf("Uploading BOM: project %s:%s", projectName, projectVersion)

uploadToken, err := dt.Client.BOM.Upload(ctx, dtrack.BOMUploadRequest{
ProjectName: projectName,
ProjectVersion: projectVersion,
ParentName: parentName,
ParentVersion: parentVersion,
AutoCreate: true,
BOM: base64.StdEncoding.EncodeToString(bom),
})
Expand Down
8 changes: 4 additions & 4 deletions mock/dependencytrack_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion uploader/uploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,17 @@ func (u *Upload) Run(ctx context.Context, input []byte) error {
projectTags = append(projectTags, t)
}

if err := u.dtrack.UploadBOM(ctx, projectName, projectVersion, sbom.BOM()); err != nil {
parentName, err := tpl.Render(u.config.ParentName)
if err != nil {
return err
}

parentVersion, err := tpl.Render(u.config.ParentVersion)
if err != nil {
return err
}

if err := u.dtrack.UploadBOM(ctx, projectName, projectVersion, parentName, parentVersion, sbom.BOM()); err != nil {
return err
}

Expand Down
14 changes: 13 additions & 1 deletion uploader/uploader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ func TestUpload_Run(t *testing.T) {
projectName string
projectVersion string
projectTags []string
parentName string
parentVersion string
err error
}
type mockAddTagsToProject struct {
Expand All @@ -57,6 +59,8 @@ func TestUpload_Run(t *testing.T) {
APIKey: "apiKey",
ProjectName: "[[.sbomReport.report.artifact.repository]]",
ProjectVersion: "[[.sbomReport.report.artifact.tag]]",
ParentName: "[[.sbomReport.metadata.namespace]]",
ParentVersion: "[[.sbomReport.report.artifact.tag]]",
ProjectTags: []string{
"test",
"kube_namespace:[[.sbomReport.metadata.namespace]]",
Expand All @@ -67,6 +71,8 @@ func TestUpload_Run(t *testing.T) {
enable: true,
projectName: "library/alpine",
projectVersion: "latest",
parentName: "default",
parentVersion: "latest",
projectTags: []string{
"test",
"kube_namespace:default",
Expand All @@ -92,6 +98,8 @@ func TestUpload_Run(t *testing.T) {
APIKey: "apiKey",
ProjectName: "[[.sbomReport.report.artifact.repository]]",
ProjectVersion: "[[.sbomReport.report.artifact.tag]]",
ParentName: "[[.sbomReport.metadata.namespace]]",
ParentVersion: "[[.sbomReport.report.artifact.tag]]",
ProjectTags: []string{
"test",
"kube_namespace:[[.sbomReport.metadata.namespace]]",
Expand All @@ -107,13 +115,17 @@ func TestUpload_Run(t *testing.T) {
APIKey: "apiKey",
ProjectName: "[[.sbomReport.report.artifact.repository]]",
ProjectVersion: "[[.sbomReport.report.artifact.tag]]",
ParentName: "[[.sbomReport.metadata.namespace]]",
ParentVersion: "[[.sbomReport.report.artifact.tag]]",
ProjectTags: []string{},
},
input: sbomReportV1alpha1,
mockUploadBOM: mockUploadBOM{
enable: true,
projectName: "library/alpine",
projectVersion: "latest",
parentName: "default",
parentVersion: "latest",
projectTags: []string{
"test",
"kube_namespace:default",
Expand All @@ -129,7 +141,7 @@ func TestUpload_Run(t *testing.T) {

for _, tc := range testCases {
if tc.mockUploadBOM.enable {
mockDTrack.EXPECT().UploadBOM(ctx, tc.mockUploadBOM.projectName, tc.mockUploadBOM.projectVersion, gomock.Any()).Return(tc.mockUploadBOM.err)
mockDTrack.EXPECT().UploadBOM(ctx, tc.mockUploadBOM.projectName, tc.mockUploadBOM.projectVersion, tc.mockUploadBOM.parentName, tc.mockUploadBOM.parentVersion, gomock.Any()).Return(tc.mockUploadBOM.err)
}
if tc.mockAddTagsToProject.enable {
mockDTrack.EXPECT().AddTagsToProject(ctx, tc.mockAddTagsToProject.projectName, tc.mockAddTagsToProject.projectVersion, tc.mockAddTagsToProject.projectTags).Return(tc.mockAddTagsToProject.err)
Expand Down

0 comments on commit 473076c

Please sign in to comment.