diff --git a/pom.xml b/pom.xml index 25f62e7f..b0ad230f 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,8 @@ true 1.23 1 - 5.0.3-01 + + 5.0.4-SNAPSHOT 36 4.1 @@ -205,6 +206,19 @@ 3.4.2 + + + org.apache.commons + commons-compress + 1.26.0 + + + com.google.guava + guava + 32.1.2-jre + + + org.codehaus.groovy groovy-all diff --git a/src/main/java/org/sonatype/nexus/ci/iq/CallflowConfiguration.groovy b/src/main/java/org/sonatype/nexus/ci/iq/CallflowConfiguration.groovy new file mode 100644 index 00000000..587ea236 --- /dev/null +++ b/src/main/java/org/sonatype/nexus/ci/iq/CallflowConfiguration.groovy @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-present Sonatype, Inc. All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. + */ + +package org.sonatype.nexus.ci.iq + +import hudson.Extension +import hudson.model.AbstractDescribableImpl +import hudson.model.Descriptor +import org.kohsuke.stapler.DataBoundConstructor +import org.kohsuke.stapler.DataBoundSetter + +class CallflowConfiguration + extends AbstractDescribableImpl +{ + List callflowScanPatterns + + List callflowNamespaces + + // This is used for experimental configuration. The options will not be widely publicised but can allow us to + // internally test different callflow options + Map additionalConfiguration + + @DataBoundConstructor + CallflowConfiguration( + final List callflowScanPatterns = null, + final List callflowNamespaces = null, + final Map additionalConfiguration = null + ) { + this.callflowScanPatterns = callflowScanPatterns + this.callflowNamespaces = callflowNamespaces + this.additionalConfiguration = additionalConfiguration + } + + List getCallflowScanPatterns() { + return callflowScanPatterns + } + + @DataBoundSetter + void setCallflowScanPatterns(final List callflowScanPatterns) { + this.callflowScanPatterns = callflowScanPatterns + } + + List getCallflowNamespaces() { + return callflowNamespaces + } + + @DataBoundSetter + void setCallflowNamespaces(final List callflowNamespaces) { + this.callflowNamespaces = callflowNamespaces + } + + Map getAdditionalConfiguration() { + return this.additionalConfiguration + } + + @DataBoundSetter + void setAdditionalConfiguration(final Map additionalConfiguration) { + this.additionalConfiguration = additionalConfiguration + } + + @Extension + static class DescriptorImpl extends Descriptor + { + @Override + String getDisplayName() { + return Messages.IqPolicyEvaluation_callflowConfiguration() + } + } +} diff --git a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluator.groovy b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluator.groovy index 5e057275..0c7ba4c5 100644 --- a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluator.groovy +++ b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluator.groovy @@ -37,4 +37,8 @@ interface IqPolicyEvaluator Boolean getEnableDebugLogging() String getAdvancedProperties() + + Boolean getRunCallflow() + + CallflowConfiguration getCallflowConfiguration(); } diff --git a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorBuildStep.groovy b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorBuildStep.groovy index 22970f91..43b1d628 100644 --- a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorBuildStep.groovy +++ b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorBuildStep.groovy @@ -58,6 +58,10 @@ class IqPolicyEvaluatorBuildStep String advancedProperties + Boolean runCallflow + + CallflowConfiguration callflowConfiguration + @DataBoundConstructor @SuppressWarnings('ParameterCount') IqPolicyEvaluatorBuildStep(final String iqInstanceId, @@ -70,7 +74,10 @@ class IqPolicyEvaluatorBuildStep final Boolean failBuildOnScanningErrors, final String jobCredentialsId, final Boolean enableDebugLogging, - final String advancedProperties) + final String advancedProperties, + final Boolean runCallflow, + final CallflowConfiguration callflowConfiguration + ) { this.iqInstanceId = iqInstanceId this.jobCredentialsId = jobCredentialsId @@ -83,6 +90,8 @@ class IqPolicyEvaluatorBuildStep this.iqApplication = iqApplication this.advancedProperties = advancedProperties this.enableDebugLogging = enableDebugLogging + this.runCallflow = runCallflow + this.callflowConfiguration = callflowConfiguration } @DataBoundSetter @@ -201,5 +210,13 @@ class IqPolicyEvaluatorBuildStep def jobCredentials = jobCredentialsId ?: nxiqConfiguration?.credentialsId IqUtil.doFillIqOrganizationItems(serverUrl, jobCredentials, job) } + + Boolean getRunCallflow() { + return this.runCallflow + } + + CallflowConfiguration getCallflowConfiguration() { + return this.callflowConfiguration + } } } diff --git a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorUtil.groovy b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorUtil.groovy index 07da6e68..dea3969f 100644 --- a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorUtil.groovy +++ b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorUtil.groovy @@ -14,6 +14,7 @@ package org.sonatype.nexus.ci.iq import java.nio.file.Paths +import com.sonatype.nexus.api.common.CallflowOptions import com.sonatype.nexus.api.exception.IqClientException import com.sonatype.nexus.api.iq.ApplicationPolicyEvaluation @@ -34,11 +35,12 @@ import org.apache.commons.lang.exception.ExceptionUtils import static com.google.common.base.Preconditions.checkArgument +@SuppressWarnings(['ClassSize', 'AbcMetric']) class IqPolicyEvaluatorUtil { static final String MINIMAL_SERVER_VERSION_REQUIRED = '1.69.0' - @SuppressWarnings(['AbcMetric', 'ParameterCount', 'CyclomaticComplexity']) + @SuppressWarnings(['ParameterCount', 'CyclomaticComplexity', 'MethodSize']) static ApplicationPolicyEvaluation evaluatePolicy(final IqPolicyEvaluator iqPolicyEvaluator, final Run run, final FilePath workspace, @@ -110,7 +112,32 @@ class IqPolicyEvaluatorUtil } File workDirectory = new File(workspace.getRemote()) - evaluationResult = iqClient.evaluateApplication(applicationId, iqStage, scanResult, workDirectory) + + final CallflowOptions callflowOptions + + if (iqPolicyEvaluator.getRunCallflow()) { + listener.logger.println('callflow analysis is enabled') + + CallflowConfiguration callflowConfiguration = iqPolicyEvaluator.getCallflowConfiguration() + + callflowOptions = makeCallflowOptions( + callflowConfiguration, + remoteScanner, + workDirectory, + envVars, + iqPolicyEvaluator.iqScanPatterns + ) + } else { + callflowOptions = null + } + + evaluationResult = iqClient.evaluateApplication( + applicationId, + iqStage, + scanResult, + workDirectory, + callflowOptions as CallflowOptions + ) } finally { // clean up scan files on master and agent scanResult?.scanFile?.delete() @@ -125,7 +152,7 @@ class IqPolicyEvaluatorUtil def reportAction = new PolicyEvaluationReportAction(applicationId, iqStage, run, evaluationResult) run.addAction(reportAction) } - + Result result = handleEvaluationResult(evaluationResult, listener, applicationId, iqConfig?.hideReports) run.setResult(result) if (result == Result.FAILURE) { @@ -184,6 +211,46 @@ class IqPolicyEvaluatorUtil iqScanPatterns.collect { envVars.expand(it.scanPattern) } - null - '' } + private static CallflowOptions makeCallflowOptions( + final CallflowConfiguration callflowConfiguration, + final RemoteScanner remoteScanner, + final File workdir, + final EnvVars envVars, + final List iqScanPatterns) + { + if (callflowConfiguration == null) { + final List expandedPatterns = getScanPatterns(iqScanPatterns, envVars) + final List targets = remoteScanner.getScanTargets(workdir, expandedPatterns) + .collect { + return it.getAbsolutePath() + } + + // defaults to using same targets as original iq scan, when enabled but no additional config passed + return new CallflowOptions(targets, null, null) + } else { + List patterns = callflowConfiguration.getCallflowScanPatterns() + if (patterns == null) { + // defaults to using same targets as original iq scan, when no patterns passed with additional config + patterns = iqScanPatterns + } + + final List expandedPatterns = getScanPatterns(patterns, envVars) + + final List targets = remoteScanner.getScanTargets(workdir, expandedPatterns) + .collect { it.getAbsolutePath() } + + final Properties addtionalConfiguration = new Properties() + if (callflowConfiguration.getAdditionalConfiguration() != null) { + addtionalConfiguration.putAll(callflowConfiguration.getAdditionalConfiguration()) + } + + return new CallflowOptions( + targets, + callflowConfiguration.getCallflowNamespaces(), + addtionalConfiguration) + } + } + private static List getExpandedModuleExcludes(final List moduleExcludes, final EnvVars envVars) { diff --git a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorWorkflowStep.groovy b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorWorkflowStep.groovy index 0842ff92..94fabf02 100644 --- a/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorWorkflowStep.groovy +++ b/src/main/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorWorkflowStep.groovy @@ -54,6 +54,10 @@ class IqPolicyEvaluatorWorkflowStep String advancedProperties + Boolean runCallflow + + CallflowConfiguration callflowConfiguration; + @DataBoundSetter void setIqOrganization(final String iqOrganization) { this.iqOrganization = iqOrganization @@ -89,6 +93,16 @@ class IqPolicyEvaluatorWorkflowStep this.enableDebugLogging = enableDebugLogging } + @DataBoundSetter + void setRunCallflow(Boolean runCallflow) { + this.runCallflow = runCallflow + } + + @DataBoundSetter + void setCallflowConfiguration(final CallflowConfiguration callflowConfiguration) { + this.callflowConfiguration = callflowConfiguration + } + @DataBoundSetter void setAdvancedProperties(final String advancedProperties) { this.advancedProperties = advancedProperties @@ -124,6 +138,16 @@ class IqPolicyEvaluatorWorkflowStep this.iqInstanceId = iqInstanceId ?: IqUtil.getFirstIqConfiguration()?.id } + @Override + Boolean getRunCallflow() { + return this.runCallflow + } + + @Override + CallflowConfiguration getCallflowConfiguration() { + return this.callflowConfiguration + } + @Extension static final class DescriptorImpl extends AbstractStepDescriptorImpl diff --git a/src/main/resources/org/sonatype/nexus/ci/iq/Messages.properties b/src/main/resources/org/sonatype/nexus/ci/iq/Messages.properties index 9fbe1f19..53617c68 100644 --- a/src/main/resources/org/sonatype/nexus/ci/iq/Messages.properties +++ b/src/main/resources/org/sonatype/nexus/ci/iq/Messages.properties @@ -50,6 +50,8 @@ IqPolicyEvaluation.NoViolations=No Violations IqPolicyEvaluation.LegacyViolations={0} Legacy {0,choice,0#Violations|1#Violation|1< Violations} IqPolicyEvaluation.TotalViolations={0} Violations IqPolicyEvaluation.AffectedComponents=affecting {0} out of {1} components evaluated +IqPolicyEvaluation.runCallflow=Flag indicating if callflow analysis should be ran +IqPolicyEvaluation.callflowConfiguration=Additional callflow configuration options PolicyFailureMessageFormatter.PolicyFailing=Nexus IQ reports policy failing due to {0} PolicyFailureMessageFormatter.PolicyWarning=Nexus IQ reports policy warning due to {0} diff --git a/src/test/java/org/sonatype/nexus/ci/config/ComToOrgMigratorIntegrationTest.groovy b/src/test/java/org/sonatype/nexus/ci/config/ComToOrgMigratorIntegrationTest.groovy index 7922c655..f018023e 100644 --- a/src/test/java/org/sonatype/nexus/ci/config/ComToOrgMigratorIntegrationTest.groovy +++ b/src/test/java/org/sonatype/nexus/ci/config/ComToOrgMigratorIntegrationTest.groovy @@ -101,7 +101,7 @@ class ComToOrgMigratorIntegrationTest 1 * iqClient.verifyOrCreateApplication(*_) >> true 1 * iqClient.getLicensedFeatures() >> [] 1 * iqClient.scan(*_) >> new ScanResult(new Scan(), File.createTempFile('dummy-scan', '.xml.gz')) - 1 * iqClient.evaluateApplication('sample-app', 'build', _, _) >> new ApplicationPolicyEvaluation( + 1 * iqClient.evaluateApplication('sample-app', 'build', *_) >> new ApplicationPolicyEvaluation( 0, 1, 2, 3, 11, 12, 13, 0, 1, [], 'http://server/link/to/report') then: 'the return code is successful' @@ -124,7 +124,7 @@ class ComToOrgMigratorIntegrationTest then: 'the application is scanned and evaluated' 1 * iqClient.verifyOrCreateApplication(*_) >> true 1 * iqClient.scan(*_) >> new ScanResult(new Scan(), File.createTempFile('dummy-scan', '.xml.gz')) - 1 * iqClient.evaluateApplication('sample-app', 'build', _, _) >> new ApplicationPolicyEvaluation( + 1 * iqClient.evaluateApplication('sample-app', 'build', *_) >> new ApplicationPolicyEvaluation( 0, 1, 2, 3, 11, 12, 13, 0, 1, [], 'http://server/link/to/report') then: 'the expected result is returned' diff --git a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorDescriptorTest.groovy b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorDescriptorTest.groovy index b1e2f1a7..282185d8 100644 --- a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorDescriptorTest.groovy +++ b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorDescriptorTest.groovy @@ -383,7 +383,7 @@ abstract class IqPolicyEvaluatorDescriptorTest when: def buildStep = new IqPolicyEvaluatorBuildStep(null, null, null, null, null, null, null, null, - 'jobSpecificCredentialsId', null, null) + 'jobSpecificCredentialsId', null, null, false, null) then: buildStep.jobCredentialsId == 'jobSpecificCredentialsId' diff --git a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorIntegrationTest.groovy b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorIntegrationTest.groovy index d693a203..c577ef05 100644 --- a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorIntegrationTest.groovy +++ b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorIntegrationTest.groovy @@ -16,7 +16,6 @@ import com.sonatype.insight.scan.model.Scan import com.sonatype.nexus.api.exception.IqClientException import com.sonatype.nexus.api.iq.Action import com.sonatype.nexus.api.iq.ApplicationPolicyEvaluation -import com.sonatype.nexus.api.iq.PolicyAlert import com.sonatype.nexus.api.iq.internal.InternalIqClient import com.sonatype.nexus.api.iq.internal.InternalIqClientBuilder import com.sonatype.nexus.api.iq.scan.ScanResult @@ -282,7 +281,7 @@ class IqPolicyEvaluatorIntegrationTest FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], false, false, 'cred-id', - null, null)) + null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -304,7 +303,7 @@ class IqPolicyEvaluatorIntegrationTest FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList. add(new IqPolicyEvaluatorBuildStep('id2', 'stage', orgId, new SelectedApplication(appId), [], [], false, false, 'cred-id', - null, null)) + null, null, false, null)) List nxiqConfiguration = [ new NxiqConfiguration('id1', 'int-id1', 'display-name1', 'http://server/url1', 'no-cred', false), new NxiqConfiguration('id2', 'int-id2', 'display-name2', 'http://server/url1', 'cred-id', false) @@ -388,7 +387,7 @@ class IqPolicyEvaluatorIntegrationTest def failBuildOnNetworkError = false FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList.add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - failBuildOnNetworkError, false, 'cred-id', null, null)) + failBuildOnNetworkError, false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -410,7 +409,7 @@ class IqPolicyEvaluatorIntegrationTest FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], true, false, - 'cred-id', null, null)) + 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -459,7 +458,7 @@ class IqPolicyEvaluatorIntegrationTest def failBuildOnNetworkError = false FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList.add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - failBuildOnNetworkError, false, 'cred-id', null, null)) + failBuildOnNetworkError, false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -641,7 +640,7 @@ class IqPolicyEvaluatorIntegrationTest def failBuildOnNetworkError = false FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList.add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - failBuildOnNetworkError, false, 'cred-id', null, null)) + failBuildOnNetworkError, false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -692,7 +691,7 @@ class IqPolicyEvaluatorIntegrationTest def failBuildOnNetworkError = false FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList.add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - failBuildOnNetworkError, false, 'cred-id', null, null)) + failBuildOnNetworkError, false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -710,7 +709,7 @@ class IqPolicyEvaluatorIntegrationTest def failBuildOnNetworkError = false FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList.add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - failBuildOnNetworkError, false, 'cred-id', null, null)) + failBuildOnNetworkError, false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -776,7 +775,7 @@ class IqPolicyEvaluatorIntegrationTest FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new ManualApplication('app'), [], [], false, - false, 'cred-id', null, null)) + false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -785,7 +784,7 @@ class IqPolicyEvaluatorIntegrationTest then: 'the application is scanned and evaluated' 1 * iqClient.verifyOrCreateApplication('app', null) >> true 1 * iqClient.scan(*_) >> new ScanResult(new Scan(), File.createTempFile('dummy-scan', '.xml.gz')) - 1 * iqClient.evaluateApplication('app', _, _, _) >> new ApplicationPolicyEvaluation( + 1 * iqClient.evaluateApplication('app', *_) >> new ApplicationPolicyEvaluation( 0, 1, 2, 3, 11, 12, 13, 0, 1, [], 'http://server/link/to/report') then: 'the return code is successful' @@ -802,7 +801,7 @@ class IqPolicyEvaluatorIntegrationTest FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new ManualApplication('$APP'), [], [], false, - false, 'cred-id', null, null)) + false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -811,7 +810,7 @@ class IqPolicyEvaluatorIntegrationTest then: 'the application is scanned and evaluated' 1 * iqClient.verifyOrCreateApplication('app', null) >> true 1 * iqClient.scan(*_) >> new ScanResult(new Scan(), File.createTempFile('dummy-scan', '.xml.gz')) - 1 * iqClient.evaluateApplication('app', _, _, _) >> new ApplicationPolicyEvaluation( + 1 * iqClient.evaluateApplication('app', *_) >> new ApplicationPolicyEvaluation( 0, 1, 2, 3, 11, 12, 13, 0, 1, [], 'http://server/link/to/report') then: 'the return code is successful' @@ -823,7 +822,7 @@ class IqPolicyEvaluatorIntegrationTest FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins() def url = 'http://a.com/b/c' def prop = new EnvironmentVariablesNodeProperty() @@ -854,7 +853,7 @@ class IqPolicyEvaluatorIntegrationTest project.setScm(new ExtractResourceSCM(path)) project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], false, - false, 'cred-id', null, null)) + false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -876,7 +875,7 @@ class IqPolicyEvaluatorIntegrationTest FreeStyleProject project = jenkins.createFreeStyleProject() project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -1055,7 +1054,7 @@ class IqPolicyEvaluatorIntegrationTest Boolean enableDebugLogging = true project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', enableDebugLogging, null)) + false, false, 'cred-id', enableDebugLogging, null, false, null)) configureJenkins() when: 'the build is scheduled' @@ -1078,7 +1077,7 @@ class IqPolicyEvaluatorIntegrationTest Boolean enableDebugLogging = false project.buildersList. add(new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', enableDebugLogging, null)) + false, false, 'cred-id', enableDebugLogging, null, false, null)) configureJenkins() when: 'the build is scheduled' diff --git a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorSlaveIntegrationTest.groovy b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorSlaveIntegrationTest.groovy index f8127c57..0f4d5fe5 100644 --- a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorSlaveIntegrationTest.groovy +++ b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorSlaveIntegrationTest.groovy @@ -56,7 +56,7 @@ class IqPolicyEvaluatorSlaveIntegrationTest project.assignedNode = jenkins.createSlave() project.buildersList. add(new IqPolicyEvaluatorBuildStep('id', 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins(jenkins.jenkins, wireMockRule.port()) and: 'a mock IQ server stub' @@ -79,7 +79,7 @@ class IqPolicyEvaluatorSlaveIntegrationTest project.assignedNode = jenkins.createSlave() project.buildersList. add(new IqPolicyEvaluatorBuildStep('id', 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins(jenkins.jenkins, wireMockRule.port()) and: 'a mock IQ server stub' @@ -98,7 +98,7 @@ class IqPolicyEvaluatorSlaveIntegrationTest project.assignedNode = jenkins.createSlave() project.buildersList. add(new IqPolicyEvaluatorBuildStep('id', 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins(jenkins.jenkins, wireMockRule.port()) and: 'a mock IQ server stub' @@ -182,7 +182,7 @@ class IqPolicyEvaluatorSlaveIntegrationTest project.assignedNode = jenkins.createSlave() project.buildersList. add(new IqPolicyEvaluatorBuildStep('id', 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins(jenkins.jenkins, wireMockRule.port()) and: 'a mock IQ server stub' @@ -206,7 +206,7 @@ class IqPolicyEvaluatorSlaveIntegrationTest project.setScm(new ExtractResourceSCM(path)) project.buildersList. add(new IqPolicyEvaluatorBuildStep('id', 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins(jenkins.jenkins, wireMockRule.port()) and: 'a mock IQ server stub' @@ -281,7 +281,7 @@ class IqPolicyEvaluatorSlaveIntegrationTest project.assignedNode = jenkins.createSlave() project.buildersList. add(new IqPolicyEvaluatorBuildStep('id', 'stage', null, new SelectedApplication('app'), [], [], - false, false, 'cred-id', null, null)) + false, false, 'cred-id', null, null, false, null)) configureJenkins(jenkins.jenkins, wireMockRule.port(), true) and: 'a mock IQ server stub' diff --git a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorTest.groovy b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorTest.groovy index f0f32bf1..15bbbb80 100644 --- a/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorTest.groovy +++ b/src/test/java/org/sonatype/nexus/ci/iq/IqPolicyEvaluatorTest.groovy @@ -14,6 +14,7 @@ package org.sonatype.nexus.ci.iq import com.sonatype.insight.scan.model.Scan import com.sonatype.insight.scan.model.ScanSummary +import com.sonatype.nexus.api.common.CallflowOptions import com.sonatype.nexus.api.exception.IqClientException import com.sonatype.nexus.api.iq.Action import com.sonatype.nexus.api.iq.ApplicationPolicyEvaluation @@ -94,8 +95,7 @@ class IqPolicyEvaluatorTest GroovyMock(RemoteScannerFactory, global: true) GroovyMock(RemoteRepositoryUrlFinderFactory, global: true) iqClient.getLicensedFeatures() >> [] - iqClient.evaluateApplication('appId', 'stage', _, _) >> new ApplicationPolicyEvaluation( - 0, 0, 0, 0, 0, 0, 0, 0, 0, [], reportUrl) + iqClient.evaluateApplication('appId', 'stage', *_) >> getAnyApplicationPolicyEvaluation() IqClientFactory.getIqClient(*_) >> iqClient remoteScanResult.copyToLocalScanResult() >> scanResult scanResult.scanFile >> localScanFile @@ -115,7 +115,7 @@ class IqPolicyEvaluatorTest globalConfiguration.iqConfigs.add(new NxiqConfiguration('id2', 'internalId2', 'displayName2', 'serverUrl2', 'credentialsId2', false)) globalConfiguration.save() - def buildStep = new IqPolicyEvaluatorBuildStep(null, null, null, null, null, null, null, null, null, null, null) + def buildStep = new IqPolicyEvaluatorBuildStep(null, null, null, null, null, null, null, null, null, null, null, null, null) when: buildStep.setIqInstanceId(iqInstanceId) @@ -157,8 +157,8 @@ class IqPolicyEvaluatorTest def 'it retrieves proprietary config followed by remote scan followed by evaluation in correct order (happy path)'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), - [new ScanPattern('*.jar')], [], false, false, null, null, null) - def evaluationResult = new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, emptyList(), reportUrl) + [new ScanPattern('*.jar')], [], false, false, null, null, null, false, null) + def evaluationResult = getAnyApplicationPolicyEvaluation() def remoteScanner = Mock(RemoteScanner) when: @@ -174,7 +174,7 @@ class IqPolicyEvaluatorTest 1 * channel.call(remoteScanner) >> remoteScanResult then: 'evaluates the result' - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> evaluationResult + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> evaluationResult then: 'delete the temp scan file' 1 * localScanFile.delete() >> true } @@ -184,7 +184,7 @@ class IqPolicyEvaluatorTest def remoteScanner = Mock(RemoteScanner) def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('/path1/$SCAN_PATTERN/path2/')], - [], false, false, '131-cred', null, null) + [], false, false, '131-cred', null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) @@ -200,7 +200,7 @@ class IqPolicyEvaluatorTest setup: def remoteScanner = Mock(RemoteScanner) def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), - [new ScanPattern('/path1/$NONEXISTENT_SCAN_PATTERN/path2/')], [], false, false, '131-cred', null, null) + [new ScanPattern('/path1/$NONEXISTENT_SCAN_PATTERN/path2/')], [], false, false, '131-cred', null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) @@ -216,7 +216,7 @@ class IqPolicyEvaluatorTest setup: def remoteScanner = Mock(RemoteScanner) def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [], - [new ModuleExclude('/path1/$NONEXISTENT_MODULE_EXCLUDE/path2/')], false, false, '131-cred', null, null) + [new ModuleExclude('/path1/$NONEXISTENT_MODULE_EXCLUDE/path2/')], false, false, '131-cred', null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) @@ -233,7 +233,7 @@ class IqPolicyEvaluatorTest setup: def remoteScanner = Mock(RemoteScanner) def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [], - [new ModuleExclude('/path1/$MODULE_EXCLUDE/path2/')], false, false, '131-cred', null, null) + [new ModuleExclude('/path1/$MODULE_EXCLUDE/path2/')], false, false, '131-cred', null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) @@ -250,7 +250,7 @@ class IqPolicyEvaluatorTest setup: iqClient.getProprietaryConfigForApplicationEvaluation('appId') >> { throw exception } def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - failBuildOnNetworkError, false, '131-cred', null, null) + failBuildOnNetworkError, false, '131-cred', null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) @@ -273,7 +273,7 @@ class IqPolicyEvaluatorTest setup: iqClient.getProprietaryConfigForApplicationEvaluation('appId') >> { throw exception } def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - failBuildOnNetworkError, false, '131-cred', null, null) + failBuildOnNetworkError, false, '131-cred', null, null, false, null) PrintStream logger = Mock() BuildListener listener = Mock() { getLogger() >> logger @@ -298,7 +298,7 @@ class IqPolicyEvaluatorTest setup: iqClient.getProprietaryConfigForApplicationEvaluation('appId') >> proprietaryConfig def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) + false, false, '131-cred', null, null, false, null) RemoteScanner remoteScanner = Mock() RemoteScannerFactory.getRemoteScanner(*_) >> remoteScanner @@ -319,14 +319,14 @@ class IqPolicyEvaluatorTest setup: def failBuildOnNetworkError = false def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - failBuildOnNetworkError, false, '131-cred', null, null) + failBuildOnNetworkError, false, '131-cred', null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> { throw new IqClientException('SNAP', new IOException('CRASH')) } noExceptionThrown() and: 'delete the temp scan file' @@ -337,7 +337,7 @@ class IqPolicyEvaluatorTest def 'global no credentials are passed to the client builder when no job credentials provided'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), - [new ScanPattern('*.jar')], [], true, false, jobCredentials, null, null) + [new ScanPattern('*.jar')], [], true, false, jobCredentials, null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) @@ -356,15 +356,14 @@ class IqPolicyEvaluatorTest def 'evaluation result outcome determines build status'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) + false, false, '131-cred', null, null, false, null) when: buildStep.perform(run, launcher, Mock(BuildListener)) then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, alerts, reportUrl) + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> getAnyApplicationPolicyEvaluation(alerts) 1 * run.setResult(buildResult) and: 'delete the temp scan file' 1 * localScanFile.delete() >> true @@ -380,7 +379,7 @@ class IqPolicyEvaluatorTest def 'evaluation summary error count determines unstable status'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) + false, false, '131-cred', null, null, false, null) def scan = Mock(Scan) def summary = Mock(ScanSummary) scanResult.scan >> scan @@ -392,8 +391,7 @@ class IqPolicyEvaluatorTest then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, alerts, reportUrl) + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> getAnyApplicationPolicyEvaluation(alerts) 1 * run.setResult(buildResult) and: 'delete the temp scan file' 1 * localScanFile.delete() >> true @@ -408,7 +406,7 @@ class IqPolicyEvaluatorTest def 'Exception thrown for errors when failForScanningErrors true'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), - [new ScanPattern('*.jar')], [], false, true, '131-cred', null, null) + [new ScanPattern('*.jar')], [], false, true, '131-cred', null, null, false, null) def scan = Mock(Scan) def summary = Mock(ScanSummary) summary.errorCount >> 1 @@ -420,9 +418,7 @@ class IqPolicyEvaluatorTest then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, [], reportUrl) - + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> getAnyApplicationPolicyEvaluation() and: PolicyEvaluationException ex = thrown() ex.message == 'IQ Server evaluation of application appId failed' @@ -435,7 +431,7 @@ class IqPolicyEvaluatorTest def 'build unstable when scanning errors but failOnScanningErrors is false'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), - [new ScanPattern('*.jar')], [], false, false, '131-cred', null, null) + [new ScanPattern('*.jar')], [], false, false, '131-cred', null, null, false, null) def scan = Mock(Scan) def summary = Mock(ScanSummary) summary.errorCount >> 1 @@ -447,8 +443,7 @@ class IqPolicyEvaluatorTest then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, [], reportUrl) + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> getAnyApplicationPolicyEvaluation() 1 * run.setResult(Result.UNSTABLE) and: 'delete the temp scan file' @@ -459,7 +454,7 @@ class IqPolicyEvaluatorTest def 'Exception not thrown when failForScanningErrors true but no errors'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), - [new ScanPattern('*.jar')], [], false, true, '131-cred', null, null) + [new ScanPattern('*.jar')], [], false, true, '131-cred', null, null, false, null) def scan = Mock(Scan) def summary = Mock(ScanSummary) summary.errorCount >> 0 @@ -471,8 +466,7 @@ class IqPolicyEvaluatorTest then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, [], reportUrl) + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> getAnyApplicationPolicyEvaluation() 1 * run.setResult(Result.SUCCESS) and: 'delete the temp scan file' @@ -484,16 +478,15 @@ class IqPolicyEvaluatorTest def 'evaluation throws exception when build results in failure'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) - def policyEvaluation = new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, - [new PolicyAlert(null, [new Action(Action.ID_FAIL)])], reportUrl) + false, false, '131-cred', null, null, false, null) + def policyEvaluation = getAnyApplicationPolicyEvaluation([new PolicyAlert(null, [new Action(Action.ID_FAIL)])]) when: buildStep.perform(run, launcher, Mock(BuildListener)) then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> policyEvaluation + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> policyEvaluation 1 * run.setResult(Result.FAILURE) and: @@ -514,16 +507,15 @@ class IqPolicyEvaluatorTest summary.errorCount >> 1 def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) - def policyEvaluation = new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, - [new PolicyAlert(null, [new Action(Action.ID_FAIL)])], reportUrl) + false, false, '131-cred', null, null, false, null) + def policyEvaluation = getAnyApplicationPolicyEvaluation([new PolicyAlert(null, [new Action(Action.ID_FAIL)])]) when: buildStep.perform(run, launcher, Mock(BuildListener)) then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> policyEvaluation + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> policyEvaluation 1 * run.setResult(Result.FAILURE) 0 * run.setResult(Result.UNSTABLE) @@ -540,7 +532,7 @@ class IqPolicyEvaluatorTest def 'prints an error message on failure when configured with hideReports = #hideReports'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) + false, false, '131-cred', null, null, false, null) BuildListener listener = Mock() PrintStream log = Mock() listener.getLogger() >> log @@ -556,10 +548,8 @@ class IqPolicyEvaluatorTest then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 1, 2, 3, 11, 12, 13, 0, 0, - [new PolicyAlert(trigger, [new Action(Action.ID_FAIL)])], reportUrl) - + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> + getAnyApplicationPolicyEvaluation([new PolicyAlert(trigger, [new Action(Action.ID_FAIL)])], 11, 12, 13) and: thrown PolicyEvaluationException (hideReports ? 0 : 1) * log.println( @@ -579,7 +569,7 @@ class IqPolicyEvaluatorTest def 'prints a log message on warnings when configured with hideReports = #hideReports'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) + false, false, '131-cred', null, null, false, null) BuildListener listener = Mock() PrintStream log = Mock() listener.getLogger() >> log @@ -595,9 +585,7 @@ class IqPolicyEvaluatorTest then: 1 * iqClient.verifyOrCreateApplication(*_) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 1, 2, 3, 11, 12, 13, 0, 1, - [new PolicyAlert(trigger, [new Action(Action.ID_WARN)])], reportUrl) + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> getAnyApplicationPolicyEvaluation([new PolicyAlert(trigger, [new Action(Action.ID_WARN)])], 11, 12, 13) 1 * log.println('IQ Server evaluation of application appId detected warnings') (hideReports ? 0 : 1) * log.println( 'Nexus IQ reports policy warning due to \nPolicy(policyName) [\n Component(displayName=value, ' + @@ -615,7 +603,7 @@ class IqPolicyEvaluatorTest def 'prints a summary on success [App Id: #appId, Org Id: #orgId]'() { given: 'a configured build step' def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', orgId, new SelectedApplication(appId), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) + false, false, '131-cred', null, null, false, null) BuildListener listener = Mock() PrintStream log = Mock() listener.getLogger() >> log @@ -625,9 +613,7 @@ class IqPolicyEvaluatorTest then: 'the summary is printed' 1 * iqClient.verifyOrCreateApplication(appId, orgId) >> true - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> - new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, [], - reportUrl) + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> getAnyApplicationPolicyEvaluation() 0 * log.println('WARNING: IQ Server evaluation of application appId detected warnings.') 1 * log.println('\nThe detailed report can be viewed online at http://server/report\n' + 'Summary of policy violations: 0 critical, 0 severe, 0 moderate') @@ -646,7 +632,7 @@ class IqPolicyEvaluatorTest def 'prints proper error message when app verification fails [Org Id: #orgId]'() { given: 'a configured build step' def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', orgId, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, '131-cred', null, null) + false, false, '131-cred', null, null, false, null) BuildListener listener = Mock() PrintStream log = Mock() listener.getLogger() >> log @@ -670,7 +656,7 @@ class IqPolicyEvaluatorTest def 'prints an error message if not in node context'() { setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), - [new ScanPattern('*.jar')], [],false, false, null, null, null) + [new ScanPattern('*.jar')], [],false, false, null, null, null, false, null) def listener = Mock(BuildListener) when: @@ -686,8 +672,8 @@ class IqPolicyEvaluatorTest setup: def buildStep = new IqPolicyEvaluatorBuildStep(null, 'stage', null, new SelectedApplication('appId'), [new ScanPattern('*.jar')], [], - false, false, null, null, null) - def evaluationResult = new ApplicationPolicyEvaluation(0, 0, 0, 0, 0, 0, 0, 0, 0, emptyList(), reportUrl) + false, false, null, null, null, false, null) + def evaluationResult = getAnyApplicationPolicyEvaluation() def remoteScanner = Mock(RemoteScanner) when: @@ -709,9 +695,138 @@ class IqPolicyEvaluatorTest 1 * iqClient.addOrUpdateSourceControl('appId', repositoryUrl, _) then: 'evaluates the result' - 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _) >> evaluationResult + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, *_) >> evaluationResult and: 'delete the temp scan file' 1 * localScanFile.delete() >> true 1 * remoteScanResult.delete() >> true } + + def 'evaluates the application with default callflow options when callflow is enabled but no additional options are sent'() { + setup: + def evaluationResult = getAnyApplicationPolicyEvaluation() + + def pathReturnedByExpandingIqScanPatterns = new File("some-file.jar") + def defaultCallflowOptions = new CallflowOptions( + [pathReturnedByExpandingIqScanPatterns.getAbsolutePath()], + null, + null + ) + + def remoteScanner = Mock(RemoteScanner) + iqClient.verifyOrCreateApplication(*_) >> true + iqClient.getProprietaryConfigForApplicationEvaluation('appId') >> proprietaryConfig + RemoteScannerFactory.getRemoteScanner(*_) >> remoteScanner + channel.call(_) >> remoteScanResult + + when: + getBuildStepForCallflowTests(true, null) + .perform((AbstractBuild) run, launcher, Mock(BuildListener)) + + then: 'evaluates the results using default callflow options' + 1 * remoteScanner.getScanTargets(_, _) >> [pathReturnedByExpandingIqScanPatterns] + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _, { + it.scanTargets == defaultCallflowOptions.scanTargets && + it.namespaces == null && + it.additionalConfiguration == null + } as CallflowOptions) >> evaluationResult + } + + def 'evaluates the application with additional callflow options when callflow is enabled and additional options are sent'() { + setup: + def expectedNamespaces = ['any.namespace'] + def givenAdditionalConfig = [some: "property"] + def expectedScanTargets = [ + new File("some-path-1").getAbsolutePath(), + new File('some-path-2').getAbsolutePath() + ] + def expectedProps = new Properties().with { + it.put("some", "property") + it + } + + def evaluationResult = getAnyApplicationPolicyEvaluation() + + def remoteScanner = Mock(RemoteScanner) + iqClient.verifyOrCreateApplication(*_) >> true + iqClient.getProprietaryConfigForApplicationEvaluation('appId') >> proprietaryConfig + RemoteScannerFactory.getRemoteScanner(*_) >> remoteScanner + channel.call(_) >> remoteScanResult + + when: + getBuildStepForCallflowTests( + true, + new CallflowConfiguration( + [new ScanPattern("/some-path/**/*.jar")], + expectedNamespaces, + givenAdditionalConfig) + ).perform((AbstractBuild) run, launcher, Mock(BuildListener)) + + then: 'evaluates the results using default callflow options' + 1 * remoteScanner.getScanTargets(*_) >> [new File("some-path-1"), new File('some-path-2')] + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _, { + it.scanTargets == expectedScanTargets && + it.namespaces == expectedNamespaces && + it.additionalConfiguration == expectedProps + } as CallflowOptions) >> evaluationResult + } + + def 'evaluates the application with null for callflow options when callflow is disabled'() { + setup: + def evaluationResult = getAnyApplicationPolicyEvaluation() + + def remoteScanner = Mock(RemoteScanner) + iqClient.verifyOrCreateApplication(*_) >> true + iqClient.getProprietaryConfigForApplicationEvaluation('appId') >> proprietaryConfig + RemoteScannerFactory.getRemoteScanner(*_) >> remoteScanner + channel.call(_) >> remoteScanResult + + when: + getBuildStepForCallflowTests(false, null) + .perform((AbstractBuild) run, launcher, Mock(BuildListener)) + + then: 'evaluates the results using default callflow options' + 1 * iqClient.evaluateApplication('appId', 'stage', scanResult, _, null) >> evaluationResult + } + + private ApplicationPolicyEvaluation getAnyApplicationPolicyEvaluation( + List alerts = emptyList(), + int criticalPolicyViolationCount = 0, + int severePolicyViolationCount = 0, + int moderatePolicyViolationCount = 0 + ) { + return new ApplicationPolicyEvaluation( + 0, + 0, + 0, + 0, + criticalPolicyViolationCount, + severePolicyViolationCount, + moderatePolicyViolationCount, + 0, + 0, + alerts, + reportUrl + ) + } + + private IqPolicyEvaluatorBuildStep getBuildStepForCallflowTests( + final Boolean runCallflow, + final CallflowConfiguration callflowConfiguration + ) { + return new IqPolicyEvaluatorBuildStep( + null, + 'stage', + null, + new SelectedApplication('appId'), + [new ScanPattern('*.jar')], + [], + false, + false, + null, + null, + null, + runCallflow, + callflowConfiguration + ) + } }