diff --git a/cmd/whitesourceExecuteScan.go b/cmd/whitesourceExecuteScan.go index 69eacb967..dc29d233c 100644 --- a/cmd/whitesourceExecuteScan.go +++ b/cmd/whitesourceExecuteScan.go @@ -119,6 +119,10 @@ func whitesourceExecuteScan(config ScanOptions, _ *telemetry.CustomData, commonP } func runWhitesourceExecuteScan(config *ScanOptions, scan *ws.Scan, utils whitesourceUtils, sys whitesource, commonPipelineEnvironment *whitesourceExecuteScanCommonPipelineEnvironment) error { + if err := resolveAggregateProjectName(config, scan, sys); err != nil { + return err + } + if err := resolveProjectIdentifiers(config, scan, utils, sys); err != nil { return fmt.Errorf("failed to resolve project identifiers: %w", err) } @@ -174,7 +178,8 @@ func checkAndReportScanResults(config *ScanOptions, scan *ws.Scan, utils whiteso if !config.Reporting && !config.SecurityVulnerabilities { return nil } - if err := blockUntilReportsAreaReady(config, scan, sys); err != nil { + // Wait for WhiteSource backend to propagate the changes before downloading any reports. + if err := scan.BlockUntilReportsAreReady(sys); err != nil { return err } if config.Reporting { @@ -277,6 +282,25 @@ func resolveProductToken(config *ScanOptions, sys whitesource) error { return nil } +// resolveAggregateProjectName checks if config.ProjectToken is configured, and if so, expects a WhiteSource +// project with that token to exist. The AggregateProjectName in the ws.Scan is then configured with that +// project's name. +func resolveAggregateProjectName(config *ScanOptions, scan *ws.Scan, sys whitesource) error { + if config.ProjectToken == "" { + return nil + } + log.Entry().Infof("Attempting to resolve aggregate project name for token '%s'..", config.ProjectToken) + // If the user configured the "projectToken" parameter, we expect this project to exist in the backend. + project, err := sys.GetProjectByToken(config.ProjectToken) + if err != nil { + return err + } + nameVersion := strings.Split(project.Name, " - ") + scan.AggregateProjectName = nameVersion[0] + log.Entry().Infof("Resolve aggregate project name '%s'..", scan.AggregateProjectName) + return nil +} + // resolveAggregateProjectToken fetches the token of the WhiteSource Project specified by config.ProjectName // and stores it in config.ProjectToken. // The user can configure a projectName or projectToken of the project to be used as for aggregation of scan results. @@ -439,65 +463,6 @@ func checkProjectSecurityViolations(cvssSeverityLimit float64, project ws.Projec return nil } -func blockUntilReportsAreaReady(config *ScanOptions, scan *ws.Scan, sys whitesource) error { - // Project was scanned. We need to wait for WhiteSource backend to propagate the changes - // before downloading any reports or check security vulnerabilities. - if config.ProjectToken != "" { - // Poll status of aggregated project - if err := pollProjectStatus(config.ProjectToken, time.Now(), sys); err != nil { - return err - } - } else { - // Poll status of all scanned projects - for _, project := range scan.ScannedProjects() { - if err := pollProjectStatus(project.Token, scan.ScanTime(project.Name), sys); err != nil { - return err - } - } - } - return nil -} - -// pollProjectStatus polls project LastUpdateDate until it reflects the most recent scan -func pollProjectStatus(projectToken string, scanTime time.Time, sys whitesource) error { - return blockUntilProjectIsUpdated(projectToken, sys, scanTime, 20*time.Second, 20*time.Second, 15*time.Minute) -} - -// blockUntilProjectIsUpdated polls the project LastUpdateDate until it is newer than the given time stamp -// or no older than maxAge relative to the given time stamp. -func blockUntilProjectIsUpdated(projectToken string, sys whitesource, currentTime time.Time, maxAge, timeBetweenPolls, maxWaitTime time.Duration) error { - startTime := time.Now() - for { - project, err := sys.GetProjectByToken(projectToken) - if err != nil { - return err - } - - if project.LastUpdateDate == "" { - log.Entry().Infof("last updated time missing from project metadata, retrying") - } else { - lastUpdatedTime, err := time.Parse(ws.DateTimeLayout, project.LastUpdateDate) - if err != nil { - return fmt.Errorf("failed to parse last updated time (%s) of Whitesource project: %w", - project.LastUpdateDate, err) - } - age := currentTime.Sub(lastUpdatedTime) - if age < maxAge { - //done polling - break - } - log.Entry().Infof("time since project was last updated %v > %v, polling status...", age, maxAge) - } - - if time.Now().Sub(startTime) > maxWaitTime { - return fmt.Errorf("timeout while waiting for Whitesource scan results to be reflected in service") - } - - time.Sleep(timeBetweenPolls) - } - return nil -} - func aggregateVersionWideLibraries(config *ScanOptions, utils whitesourceUtils, sys whitesource) error { log.Entry().Infof("Aggregating list of libraries used for all projects with version: %s", config.ProductVersion) diff --git a/cmd/whitesourceExecuteScan_generated.go b/cmd/whitesourceExecuteScan_generated.go index 888ed9c3f..462d006bc 100644 --- a/cmd/whitesourceExecuteScan_generated.go +++ b/cmd/whitesourceExecuteScan_generated.go @@ -390,17 +390,12 @@ func whitesourceExecuteScanMetadata() config.StepData { Aliases: []config.Alias{}, }, { - Name: "productVersion", - ResourceRef: []config.ResourceReference{ - { - Name: "commonPipelineEnvironment", - Param: "artifactVersion", - }, - }, - Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, - Type: "string", - Mandatory: false, - Aliases: []config.Alias{}, + Name: "productVersion", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, }, { Name: "jreDownloadUrl", diff --git a/cmd/whitesourceExecuteScan_test.go b/cmd/whitesourceExecuteScan_test.go index 6b3612531..13b74d309 100644 --- a/cmd/whitesourceExecuteScan_test.go +++ b/cmd/whitesourceExecuteScan_test.go @@ -145,52 +145,70 @@ func TestResolveProjectIdentifiers(t *testing.T) { }) } -func TestBlockUntilProjectIsUpdated(t *testing.T) { +func TestRunWhitesourceExecuteScan(t *testing.T) { t.Parallel() - t.Run("already new enough", func(t *testing.T) { + t.Run("fails for invalid configured project token", func(t *testing.T) { // init - nowString := "2010-05-30 00:15:00 +0100" - now, err := time.Parse(ws.DateTimeLayout, nowString) - if err != nil { - t.Fatalf(err.Error()) + config := ScanOptions{ + ScanType: "unified-agent", + BuildDescriptorFile: "my-mta.yml", + VersioningModel: "major", + ProductName: "mock-product", + ProjectToken: "no-such-project-token", + AgentDownloadURL: "https://whitesource.com/agent.jar", + AgentFileName: "ua.jar", } - lastUpdatedDate := "2010-05-30 00:15:01 +0100" - systemMock := ws.NewSystemMock(lastUpdatedDate) + utilsMock := newWhitesourceUtilsMock() + utilsMock.AddFile("wss-generated-file.config", []byte("key=value")) + systemMock := ws.NewSystemMock("ignored") + scan := newWhitesourceScan(&config) + cpe := whitesourceExecuteScanCommonPipelineEnvironment{} // test - err = blockUntilProjectIsUpdated(systemMock.Projects[0].Token, systemMock, now, 2*time.Second, 1*time.Second, 2*time.Second) + err := runWhitesourceExecuteScan(&config, scan, utilsMock, systemMock, &cpe) + // assert + assert.EqualError(t, err, "no project with token 'no-such-project-token' found in Whitesource") + assert.Equal(t, "", config.ProjectName) + assert.Equal(t, "", scan.AggregateProjectName) + }) + t.Run("retrieves aggregate project name by configured token", func(t *testing.T) { + // init + config := ScanOptions{ + BuildDescriptorFile: "my-mta.yml", + VersioningModel: "major", + AgentDownloadURL: "https://whitesource.com/agent.jar", + ReportDirectoryName: "ws-reports", + VulnerabilityReportFormat: "pdf", + Reporting: true, + AgentFileName: "ua.jar", + ProductName: "mock-product", + ProjectToken: "mock-project-token", + ScanType: "unified-agent", + } + utilsMock := newWhitesourceUtilsMock() + utilsMock.AddFile("wss-generated-file.config", []byte("key=value")) + lastUpdatedDate := time.Now().Format(ws.DateTimeLayout) + systemMock := ws.NewSystemMock(lastUpdatedDate) + scan := newWhitesourceScan(&config) + cpe := whitesourceExecuteScanCommonPipelineEnvironment{} + // test + err := runWhitesourceExecuteScan(&config, scan, utilsMock, systemMock, &cpe) // assert assert.NoError(t, err) - }) - t.Run("timeout while polling", func(t *testing.T) { - // init - nowString := "2010-05-30 00:15:00 +0100" - now, err := time.Parse(ws.DateTimeLayout, nowString) - if err != nil { - t.Fatalf(err.Error()) + // Retrieved project name is stored in scan.AggregateProjectName, but not in config.ProjectName + // in order to differentiate between aggregate-project scanning and multi-project scanning. + assert.Equal(t, "", config.ProjectName) + assert.Equal(t, "mock-project", scan.AggregateProjectName) + if assert.Len(t, utilsMock.DownloadedFiles, 1) { + assert.Equal(t, ws.DownloadedFile{ + SourceURL: "https://whitesource.com/agent.jar", + FilePath: "ua.jar", + }, utilsMock.DownloadedFiles[0]) } - lastUpdatedDate := "2010-05-30 00:07:00 +0100" - systemMock := ws.NewSystemMock(lastUpdatedDate) - // test - err = blockUntilProjectIsUpdated(systemMock.Projects[0].Token, systemMock, now, 2*time.Second, 1*time.Second, 1*time.Second) - // assert - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "timeout while waiting") - } - }) - t.Run("timeout while polling, no update time", func(t *testing.T) { - // init - nowString := "2010-05-30 00:15:00 +0100" - now, err := time.Parse(ws.DateTimeLayout, nowString) - if err != nil { - t.Fatalf(err.Error()) - } - systemMock := ws.NewSystemMock("") - // test - err = blockUntilProjectIsUpdated(systemMock.Projects[0].Token, systemMock, now, 2*time.Second, 1*time.Second, 1*time.Second) - // assert - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "timeout while waiting") + if assert.Len(t, cpe.custom.whitesourceProjectNames, 1) { + assert.Equal(t, []string{"mock-project - 1"}, cpe.custom.whitesourceProjectNames) } + assert.True(t, utilsMock.HasWrittenFile("ws-reports/mock-project - 1-vulnerability-report.pdf")) + assert.True(t, utilsMock.HasWrittenFile("ws-reports/mock-project - 1-risk-report.pdf")) }) } diff --git a/pkg/whitesource/scan.go b/pkg/whitesource/scan.go index a6f2f3f99..861f8887e 100644 --- a/pkg/whitesource/scan.go +++ b/pkg/whitesource/scan.go @@ -28,18 +28,31 @@ func (s *Scan) init() { } } +func (s *Scan) versionSuffix() string { + return " - " + s.ProductVersion +} + // AppendScannedProject checks that no Project with the same name is already contained in the list of scanned projects, // and appends a new Project with the given name. The global product version is appended to the name. func (s *Scan) AppendScannedProject(projectName string) error { - return s.AppendScannedProjectVersion(projectName + " - " + s.ProductVersion) + if len(projectName) == 0 { + return fmt.Errorf("projectName must not be empty") + } + if strings.HasSuffix(projectName, s.versionSuffix()) { + return fmt.Errorf("projectName is not expected to include the product version already") + } + return s.AppendScannedProjectVersion(projectName + s.versionSuffix()) } // AppendScannedProjectVersion checks that no Project with the same name is already contained in the list of scanned // projects, and appends a new Project with the given name (which is expected to include the product version). func (s *Scan) AppendScannedProjectVersion(projectName string) error { - if !strings.HasSuffix(projectName, " - "+s.ProductVersion) { + if !strings.HasSuffix(projectName, s.versionSuffix()) { return fmt.Errorf("projectName is expected to include the product version") } + if len(projectName) == len(s.versionSuffix()) { + return fmt.Errorf("projectName consists only of the product version") + } s.init() _, exists := s.scannedProjects[projectName] if exists { diff --git a/pkg/whitesource/scanNPM_test.go b/pkg/whitesource/scanNPM_test.go index 5bf1c20b5..f3d8744df 100644 --- a/pkg/whitesource/scanNPM_test.go +++ b/pkg/whitesource/scanNPM_test.go @@ -85,8 +85,8 @@ func TestExecuteScanNPM(t *testing.T) { // assert assert.NoError(t, err) expectedNpmInstalls := []NpmInstall{ - {currentDir: "app", packageJSON: []string{"package.json"}}, - {currentDir: "", packageJSON: []string{"package.json"}}, + {CurrentDir: "app", PackageJSON: []string{"package.json"}}, + {CurrentDir: "", PackageJSON: []string{"package.json"}}, } assert.Equal(t, expectedNpmInstalls, utilsMock.NpmInstalledModules) assert.True(t, utilsMock.HasRemovedFile("package-lock.json")) diff --git a/pkg/whitesource/scanPolling.go b/pkg/whitesource/scanPolling.go new file mode 100644 index 000000000..8ced71dcf --- /dev/null +++ b/pkg/whitesource/scanPolling.go @@ -0,0 +1,75 @@ +package whitesource + +import ( + "fmt" + "github.com/SAP/jenkins-library/pkg/log" + "time" +) + +type whitesourcePoller interface { + GetProjectByToken(projectToken string) (Project, error) +} + +// BlockUntilReportsAreReady polls the WhiteSource system for all projects known to the Scan and blocks +// until their LastUpdateDate time stamp is from within the last 20 seconds. +func (s *Scan) BlockUntilReportsAreReady(sys whitesourcePoller) error { + for _, project := range s.ScannedProjects() { + if err := pollProjectStatus(project.Token, s.ScanTime(project.Name), sys); err != nil { + return err + } + } + return nil +} + +type pollOptions struct { + scanTime time.Time + maxAge time.Duration + timeBetweenPolls time.Duration + maxWaitTime time.Duration +} + +// pollProjectStatus polls project LastUpdateDate until it reflects the most recent scan +func pollProjectStatus(projectToken string, scanTime time.Time, sys whitesourcePoller) error { + options := pollOptions{ + scanTime: scanTime, + maxAge: 20 * time.Second, + timeBetweenPolls: 20 * time.Second, + maxWaitTime: 15 * time.Minute, + } + return blockUntilProjectIsUpdated(projectToken, sys, options) +} + +// blockUntilProjectIsUpdated polls the project LastUpdateDate until it is newer than the given time stamp +// or no older than maxAge relative to the given time stamp. +func blockUntilProjectIsUpdated(projectToken string, sys whitesourcePoller, options pollOptions) error { + startTime := time.Now() + for { + project, err := sys.GetProjectByToken(projectToken) + if err != nil { + return err + } + + if project.LastUpdateDate == "" { + log.Entry().Infof("last updated time missing from project metadata, retrying") + } else { + lastUpdatedTime, err := time.Parse(DateTimeLayout, project.LastUpdateDate) + if err != nil { + return fmt.Errorf("failed to parse last updated time (%s) of Whitesource project: %w", + project.LastUpdateDate, err) + } + age := options.scanTime.Sub(lastUpdatedTime) + if age < options.maxAge { + //done polling + break + } + log.Entry().Infof("time since project was last updated %v > %v, polling status...", age, options.maxAge) + } + + if time.Now().Sub(startTime) > options.maxWaitTime { + return fmt.Errorf("timeout while waiting for Whitesource scan results to be reflected in service") + } + + time.Sleep(options.timeBetweenPolls) + } + return nil +} diff --git a/pkg/whitesource/scanPolling_test.go b/pkg/whitesource/scanPolling_test.go new file mode 100644 index 000000000..668f6d515 --- /dev/null +++ b/pkg/whitesource/scanPolling_test.go @@ -0,0 +1,53 @@ +package whitesource + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" + "time" +) + +func TestBlockUntilProjectIsUpdated(t *testing.T) { + t.Parallel() + + nowString := "2010-05-30 00:15:00 +0100" + now, err := time.Parse(DateTimeLayout, nowString) + require.NoError(t, err) + options := pollOptions{ + scanTime: now, + maxAge: 2 * time.Second, + timeBetweenPolls: 1 * time.Second, + maxWaitTime: 1 * time.Second, + } + + t.Run("already new enough", func(t *testing.T) { + // init + lastUpdatedDate := "2010-05-30 00:15:01 +0100" + systemMock := NewSystemMock(lastUpdatedDate) + // test + err = blockUntilProjectIsUpdated(systemMock.Projects[0].Token, systemMock, options) + // assert + assert.NoError(t, err) + }) + t.Run("timeout while polling", func(t *testing.T) { + // init + lastUpdatedDate := "2010-05-30 00:07:00 +0100" + systemMock := NewSystemMock(lastUpdatedDate) + // test + err = blockUntilProjectIsUpdated(systemMock.Projects[0].Token, systemMock, options) + // assert + if assert.Error(t, err) { + assert.Contains(t, err.Error(), "timeout while waiting") + } + }) + t.Run("timeout while polling, no update time", func(t *testing.T) { + // init + systemMock := NewSystemMock("") + // test + err = blockUntilProjectIsUpdated(systemMock.Projects[0].Token, systemMock, options) + // assert + if assert.Error(t, err) { + assert.Contains(t, err.Error(), "timeout while waiting") + } + }) +} diff --git a/pkg/whitesource/scanUA.go b/pkg/whitesource/scanUA.go index ae23d71a4..f11220836 100644 --- a/pkg/whitesource/scanUA.go +++ b/pkg/whitesource/scanUA.go @@ -18,6 +18,10 @@ func (s *Scan) ExecuteUAScan(config *ScanOptions, utils Utils) error { return err } + if err := s.AppendScannedProject(s.AggregateProjectName); err != nil { + return err + } + return utils.RunExecutable("java", "-jar", config.AgentFileName, "-d", ".", "-c", config.ConfigFilePath, "-apiKey", config.OrgToken, "-userKey", config.UserToken, "-project", s.AggregateProjectName, "-product", config.ProductName, "-productVersion", s.ProductVersion) diff --git a/pkg/whitesource/scanUA_test.go b/pkg/whitesource/scanUA_test.go index 7e884c1fb..777b92e01 100644 --- a/pkg/whitesource/scanUA_test.go +++ b/pkg/whitesource/scanUA_test.go @@ -28,9 +28,8 @@ func TestExecuteScanUA(t *testing.T) { scan := newTestScan(&config) // test err := scan.ExecuteUAScan(&config, utilsMock) - // many assert + // assert require.NoError(t, err) - content, err := utilsMock.FileRead("ua.cfg") require.NoError(t, err) contentAsString := string(content) @@ -62,6 +61,7 @@ func TestExecuteScanUA(t *testing.T) { // init config := ScanOptions{ ScanType: "unified-agent", + ProjectName: "mock-project", AgentDownloadURL: "https://download.ua.org/agent.jar", AgentFileName: "unified-agent.jar", } @@ -70,16 +70,17 @@ func TestExecuteScanUA(t *testing.T) { scan := newTestScan(&config) // test err := scan.ExecuteUAScan(&config, utilsMock) - // many assert + // assert require.NoError(t, err) require.Len(t, utilsMock.DownloadedFiles, 1) - assert.Equal(t, "https://download.ua.org/agent.jar", utilsMock.DownloadedFiles[0].sourceURL) - assert.Equal(t, "unified-agent.jar", utilsMock.DownloadedFiles[0].filePath) + assert.Equal(t, "https://download.ua.org/agent.jar", utilsMock.DownloadedFiles[0].SourceURL) + assert.Equal(t, "unified-agent.jar", utilsMock.DownloadedFiles[0].FilePath) }) t.Run("UA is NOT downloaded", func(t *testing.T) { // init config := ScanOptions{ ScanType: "unified-agent", + ProjectName: "mock-project", AgentDownloadURL: "https://download.ua.org/agent.jar", AgentFileName: "unified-agent.jar", } @@ -89,7 +90,7 @@ func TestExecuteScanUA(t *testing.T) { scan := newTestScan(&config) // test err := scan.ExecuteUAScan(&config, utilsMock) - // many assert + // assert require.NoError(t, err) assert.Len(t, utilsMock.DownloadedFiles, 0) }) diff --git a/pkg/whitesource/scan_test.go b/pkg/whitesource/scan_test.go index 312e3e709..1ca93d852 100644 --- a/pkg/whitesource/scan_test.go +++ b/pkg/whitesource/scan_test.go @@ -61,6 +61,36 @@ func TestAppendScannedProjectVersion(t *testing.T) { assert.Equal(t, expected, scan.scannedProjects) assert.Len(t, scan.scanTimes, 1) }) + t.Run("empty project name", func(t *testing.T) { + // init + scan := &Scan{ProductVersion: "1"} + // test + err := scan.AppendScannedProject("") + // assert + assert.EqualError(t, err, "projectName must not be empty") + assert.Len(t, scan.scannedProjects, 0) + assert.Len(t, scan.scanTimes, 0) + }) + t.Run("product version supplied wrongly", func(t *testing.T) { + // init + scan := &Scan{ProductVersion: "1"} + // test + err := scan.AppendScannedProject("name - 1") + // assert + assert.EqualError(t, err, "projectName is not expected to include the product version already") + assert.Len(t, scan.scannedProjects, 0) + assert.Len(t, scan.scanTimes, 0) + }) + t.Run("only version part in project name", func(t *testing.T) { + // init + scan := &Scan{ProductVersion: "1"} + // test + err := scan.AppendScannedProjectVersion(" - 1") + // assert + assert.EqualError(t, err, "projectName consists only of the product version") + assert.Len(t, scan.scannedProjects, 0) + assert.Len(t, scan.scanTimes, 0) + }) } func TestAppendScannedProject(t *testing.T) { diff --git a/pkg/whitesource/utilsMock.go b/pkg/whitesource/utilsMock.go index 13ab3039e..5ca96ec56 100644 --- a/pkg/whitesource/utilsMock.go +++ b/pkg/whitesource/utilsMock.go @@ -17,14 +17,14 @@ func newTestScan(config *ScanOptions) *Scan { // NpmInstall records in which directory "npm install" has been invoked and for which package.json files. type NpmInstall struct { - currentDir string - packageJSON []string + CurrentDir string + PackageJSON []string } // DownloadedFile records what URL has been downloaded to which file. type DownloadedFile struct { - sourceURL string - filePath string + SourceURL string + FilePath string } // ScanUtilsMock is an implementation of the Utils interface that can be used during tests. @@ -50,15 +50,15 @@ func (m *ScanUtilsMock) FindPackageJSONFiles(_ *ScanOptions) ([]string, error) { // InstallAllNPMDependencies mimics npm.InstallAllNPMDependencies() and records the "npm install". func (m *ScanUtilsMock) InstallAllNPMDependencies(_ *ScanOptions, packageJSONs []string) error { m.NpmInstalledModules = append(m.NpmInstalledModules, NpmInstall{ - currentDir: m.CurrentDir, - packageJSON: packageJSONs, + CurrentDir: m.CurrentDir, + PackageJSON: packageJSONs, }) return nil } // DownloadFile mimics http.Downloader and records the downloaded file. func (m *ScanUtilsMock) DownloadFile(url, filename string, _ http.Header, _ []*http.Cookie) error { - m.DownloadedFiles = append(m.DownloadedFiles, DownloadedFile{sourceURL: url, filePath: filename}) + m.DownloadedFiles = append(m.DownloadedFiles, DownloadedFile{SourceURL: url, FilePath: filename}) return nil } diff --git a/resources/metadata/whitesource.yaml b/resources/metadata/whitesource.yaml index 14c1a40bd..2eb0ba7c5 100644 --- a/resources/metadata/whitesource.yaml +++ b/resources/metadata/whitesource.yaml @@ -222,9 +222,6 @@ spec: - PARAMETERS - STAGES - STEPS - resourceRef: - - name: commonPipelineEnvironment - param: artifactVersion - name: jreDownloadUrl type: string description: "[NOT IMPLEMENTED] URL used for downloading the Java Runtime Environment (JRE) required to run the @@ -398,109 +395,10 @@ spec: resources: - name: buildDescriptor type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: golang - name: opensourceConfiguration type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: golang - name: checkmarx type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: golang - - name: buildDescriptor - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: maven - - name: opensourceConfiguration - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: maven - - name: buildDescriptor - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: mta - - name: opensourceConfiguration - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: mta - - name: buildDescriptor - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: npm - - name: opensourceConfiguration - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: npm - - name: buildDescriptor - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: pip - - name: opensourceConfiguration - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: pip - - name: buildDescriptor - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: sbt - - name: opensourceConfiguration - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: sbt - - name: buildDescriptor - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: dub - - name: checkmarx - type: stash - conditions: - - conditionRef: strings-equal - params: - - name: scanType - value: dub outputs: resources: - name: commonPipelineEnvironment