mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
Merge branch 'master' into pr/DoNotReturnWrongValueIfOnlyAPartOfAPathCanBeResolved
This commit is contained in:
commit
2fed3f231f
@ -25,15 +25,15 @@ none
|
||||
## Exceptions
|
||||
|
||||
* `Exception`:
|
||||
* If `source` is not provided.
|
||||
* If `propertiesFile` is not provided (when using `'WAR_PROPERTIESFILE'` deployment mode).
|
||||
* If `application` is not provided (when using `'WAR_PARAMS'` deployment mode).
|
||||
* If `runtime` is not provided (when using `'WAR_PARAMS'` deployment mode).
|
||||
* If `runtimeVersion` is not provided (when using `'WAR_PARAMS'` deployment mode).
|
||||
* If `source` is not provided.
|
||||
* If `propertiesFile` is not provided (when using `'WAR_PROPERTIESFILE'` deployment mode).
|
||||
* If `application` is not provided (when using `'WAR_PARAMS'` deployment mode).
|
||||
* If `runtime` is not provided (when using `'WAR_PARAMS'` deployment mode).
|
||||
* If `runtimeVersion` is not provided (when using `'WAR_PARAMS'` deployment mode).
|
||||
* `AbortException`:
|
||||
* If neo-java-web-sdk is not installed, or `neoHome`is wrong.
|
||||
* If neo-java-web-sdk is not installed, or `neoHome`is wrong.
|
||||
* `CredentialNotFoundException`:
|
||||
* If the credentials cannot be resolved.
|
||||
* If the credentials cannot be resolved.
|
||||
|
||||
## Example
|
||||
|
||||
|
18
documentation/docs/steps/sonarExecuteScan.md
Normal file
18
documentation/docs/steps/sonarExecuteScan.md
Normal file
@ -0,0 +1,18 @@
|
||||
# ${docGenStepName}
|
||||
|
||||
## ${docGenDescription}
|
||||
|
||||
## Prerequsites
|
||||
|
||||
- The project needs a `sonar-project.properties` file that describes the project and defines certain settings, see [here](https://docs.sonarqube.org/display/SCAN/Advanced+SonarQube+Scanner+Usages#AdvancedSonarQubeScannerUsages-Multi-moduleProjectStructure).
|
||||
- A SonarQube instance needs to be defined in the Jenkins.
|
||||
|
||||
## ${docGenParameters}
|
||||
|
||||
## ${docGenConfiguration}
|
||||
|
||||
## Exceptions
|
||||
|
||||
none
|
||||
|
||||
## Examples
|
@ -10,6 +10,7 @@ nav:
|
||||
- cloudFoundryDeploy: steps/cloudFoundryDeploy.md
|
||||
- commonPipelineEnvironment: steps/commonPipelineEnvironment.md
|
||||
- containerExecuteStructureTests: steps/containerExecuteStructureTests.md
|
||||
- detectExecuteScan: steps/detectExecuteScan.md
|
||||
- dockerExecute: steps/dockerExecute.md
|
||||
- dockerExecuteOnKubernetes: steps/dockerExecuteOnKubernetes.md
|
||||
- durationMeasure: steps/durationMeasure.md
|
||||
@ -36,6 +37,7 @@ nav:
|
||||
- setupCommonPipelineEnvironment: steps/setupCommonPipelineEnvironment.md
|
||||
- slackSendNotification: steps/slackSendNotification.md
|
||||
- snykExecute: steps/snykExecute.md
|
||||
- sonarExecuteScan: steps/sonarExecuteScan.md
|
||||
- testsPublishResults: steps/testsPublishResults.md
|
||||
- transportRequestCreate: steps/transportRequestCreate.md
|
||||
- transportRequestRelease: steps/transportRequestRelease.md
|
||||
|
@ -1,4 +1,8 @@
|
||||
stages:
|
||||
Init:
|
||||
stepConditions:
|
||||
slackSendNotification:
|
||||
config: 'channel'
|
||||
'Pull-Request Voting': {}
|
||||
Build: {}
|
||||
'Additional Unit Tests': {}
|
||||
@ -18,3 +22,7 @@ stages:
|
||||
Compliance: {}
|
||||
Promote: {}
|
||||
Release: {}
|
||||
'Post Actions':
|
||||
stepConditions:
|
||||
slackSendNotification:
|
||||
config: 'channel'
|
||||
|
@ -463,6 +463,12 @@ steps:
|
||||
- 'opensourceConfiguration'
|
||||
toJson: false
|
||||
toHtml: false
|
||||
sonarExecuteScan:
|
||||
dockerImage: 'maven:3.5-jdk-8'
|
||||
instance: 'SonarCloud'
|
||||
options: []
|
||||
pullRequestProvider: 'github'
|
||||
sonarScannerDownloadUrl: 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.3.0.1492-linux.zip'
|
||||
testsPublishResults:
|
||||
failOnError: false
|
||||
junit:
|
||||
|
@ -386,11 +386,7 @@ class NeoDeployTest extends BasePiperTest {
|
||||
deployMode: 'warPropertiesFile',
|
||||
warAction: 'deploy',
|
||||
neo: [
|
||||
propertiesFile: warPropertiesFileName,
|
||||
application: 'testApp',
|
||||
runtime: 'neo-javaee6-wp',
|
||||
runtimeVersion: '2.125',
|
||||
size: 'lite'
|
||||
propertiesFile: warPropertiesFileName
|
||||
]
|
||||
)
|
||||
|
||||
@ -412,11 +408,7 @@ class NeoDeployTest extends BasePiperTest {
|
||||
deployMode: 'warPropertiesFile',
|
||||
warAction: 'rolling-update',
|
||||
neo: [
|
||||
propertiesFile: warPropertiesFileName,
|
||||
application: 'testApp',
|
||||
runtime: 'neo-javaee6-wp',
|
||||
runtimeVersion: '2.125',
|
||||
size: 'lite'
|
||||
propertiesFile: warPropertiesFileName
|
||||
])
|
||||
|
||||
Assert.assertThat(shellRule.shell,
|
||||
|
122
test/groovy/PiperPipelineStageInitTest.groovy
Normal file
122
test/groovy/PiperPipelineStageInitTest.groovy
Normal file
@ -0,0 +1,122 @@
|
||||
#!groovy
|
||||
package stages
|
||||
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExpectedException
|
||||
import org.junit.rules.RuleChain
|
||||
import util.BasePiperTest
|
||||
import util.JenkinsLoggingRule
|
||||
import util.JenkinsReadYamlRule
|
||||
import util.JenkinsStepRule
|
||||
import util.Rules
|
||||
|
||||
import static org.hamcrest.Matchers.*
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
class PiperPipelineStageInitTest extends BasePiperTest {
|
||||
private JenkinsStepRule jsr = new JenkinsStepRule(this)
|
||||
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
|
||||
private ExpectedException thrown = ExpectedException.none()
|
||||
|
||||
@Rule
|
||||
public RuleChain rules = Rules
|
||||
.getCommonRules(this)
|
||||
.around(new JenkinsReadYamlRule(this))
|
||||
.around(thrown)
|
||||
.around(jlr)
|
||||
.around(jsr)
|
||||
|
||||
private List stepsCalled = []
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
binding.variables.env.STAGE_NAME = 'Init'
|
||||
binding.setVariable('scm', {})
|
||||
|
||||
helper.registerAllowedMethod('deleteDir', [], null)
|
||||
helper.registerAllowedMethod("findFiles", [Map.class], { map ->
|
||||
switch (map.glob) {
|
||||
case 'pom.xml':
|
||||
return [new File('pom.xml')].toArray()
|
||||
default:
|
||||
return [].toArray()
|
||||
}
|
||||
})
|
||||
helper.registerAllowedMethod('piperStageWrapper', [Map.class, Closure.class], {m, body ->
|
||||
assertThat(m.stageName, is('Init'))
|
||||
return body()
|
||||
})
|
||||
helper.registerAllowedMethod('checkout', [Closure.class], {c ->
|
||||
stepsCalled.add('checkout')
|
||||
return [
|
||||
GIT_COMMIT: 'abcdef12345',
|
||||
GIT_URL: 'some.url'
|
||||
]
|
||||
})
|
||||
helper.registerAllowedMethod('setupCommonPipelineEnvironment', [Map.class], {m -> stepsCalled.add('setupCommonPipelineEnvironment')})
|
||||
helper.registerAllowedMethod('piperInitRunStageConfiguration', [Map.class], {m -> stepsCalled.add('piperInitRunStageConfiguration')})
|
||||
helper.registerAllowedMethod('slackSendNotification', [Map.class], {m -> stepsCalled.add('slackSendNotification')})
|
||||
helper.registerAllowedMethod('artifactSetVersion', [Map.class], {m -> stepsCalled.add('artifactSetVersion')})
|
||||
helper.registerAllowedMethod('pipelineStashFilesBeforeBuild', [Map.class], {m -> stepsCalled.add('pipelineStashFilesBeforeBuild')})
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInitNoBuildTool() {
|
||||
thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR buildTool')
|
||||
jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInitBuildToolDoesNotMatchProject() {
|
||||
thrown.expect(hudson.AbortException)
|
||||
thrown.expectMessage(containsString("buildTool configuration 'npm' does not fit to your project"))
|
||||
jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'npm')
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInitDefault() {
|
||||
jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'maven')
|
||||
|
||||
assertThat(stepsCalled, hasItems(
|
||||
'checkout',
|
||||
'setupCommonPipelineEnvironment',
|
||||
'piperInitRunStageConfiguration',
|
||||
'artifactSetVersion',
|
||||
'pipelineStashFilesBeforeBuild'
|
||||
))
|
||||
assertThat(stepsCalled, not(hasItems('slackSendNotification')))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInitNotOnProductiveBranch() {
|
||||
binding.variables.env.BRANCH_NAME = 'anyOtherBranch'
|
||||
|
||||
jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'maven')
|
||||
|
||||
assertThat(stepsCalled, hasItems(
|
||||
'checkout',
|
||||
'setupCommonPipelineEnvironment',
|
||||
'piperInitRunStageConfiguration',
|
||||
'pipelineStashFilesBeforeBuild'
|
||||
))
|
||||
assertThat(stepsCalled, not(hasItems('artifactSetVersion')))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInitWithSlackNotification() {
|
||||
nullScript.commonPipelineEnvironment.configuration = [runStep: [Init: [slackSendNotification: true]]]
|
||||
|
||||
jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'maven')
|
||||
|
||||
assertThat(stepsCalled, hasItems(
|
||||
'checkout',
|
||||
'setupCommonPipelineEnvironment',
|
||||
'piperInitRunStageConfiguration',
|
||||
'artifactSetVersion',
|
||||
'slackSendNotification',
|
||||
'pipelineStashFilesBeforeBuild'
|
||||
))
|
||||
}
|
||||
}
|
69
test/groovy/PiperPipelineStagePostTest.groovy
Normal file
69
test/groovy/PiperPipelineStagePostTest.groovy
Normal file
@ -0,0 +1,69 @@
|
||||
#!groovy
|
||||
package stages
|
||||
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExpectedException
|
||||
import org.junit.rules.RuleChain
|
||||
import util.BasePiperTest
|
||||
import util.JenkinsReadYamlRule
|
||||
import util.JenkinsStepRule
|
||||
import util.Rules
|
||||
|
||||
import static org.hamcrest.Matchers.*
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
class PiperPipelineStagePostTest extends BasePiperTest {
|
||||
private JenkinsStepRule jsr = new JenkinsStepRule(this)
|
||||
private ExpectedException thrown = ExpectedException.none()
|
||||
|
||||
@Rule
|
||||
public RuleChain rules = Rules
|
||||
.getCommonRules(this)
|
||||
.around(new JenkinsReadYamlRule(this))
|
||||
.around(thrown)
|
||||
.around(jsr)
|
||||
|
||||
private List stepsCalled = []
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
binding.variables.env.STAGE_NAME = 'Release'
|
||||
|
||||
helper.registerAllowedMethod('piperStageWrapper', [Map.class, Closure.class], {m, body ->
|
||||
assertThat(m.stageName, is('Release'))
|
||||
return body()
|
||||
})
|
||||
helper.registerAllowedMethod('influxWriteData', [Map.class], {m -> stepsCalled.add('influxWriteData')})
|
||||
helper.registerAllowedMethod('slackSendNotification', [Map.class], {m -> stepsCalled.add('slackSendNotification')})
|
||||
helper.registerAllowedMethod('mailSendNotification', [Map.class], {m -> stepsCalled.add('mailSendNotification')})
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPostDefault() {
|
||||
jsr.step.piperPipelineStagePost(script: nullScript, juStabUtils: utils)
|
||||
|
||||
assertThat(stepsCalled, hasItems('influxWriteData','mailSendNotification'))
|
||||
assertThat(stepsCalled, not(hasItems('slackSendNotification')))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPostNotOnProductiveBranch() {
|
||||
binding.variables.env.BRANCH_NAME = 'anyOtherBranch'
|
||||
|
||||
jsr.step.piperPipelineStagePost(script: nullScript, juStabUtils: utils)
|
||||
|
||||
assertThat(stepsCalled, hasItems('influxWriteData','mailSendNotification'))
|
||||
assertThat(stepsCalled, not(hasItems('slackSendNotification')))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPostWithSlackNotification() {
|
||||
nullScript.commonPipelineEnvironment.configuration = [runStep: ['Post Actions': [slackSendNotification: true]]]
|
||||
|
||||
jsr.step.piperPipelineStagePost(script: nullScript, juStabUtils: utils)
|
||||
|
||||
assertThat(stepsCalled, hasItems('influxWriteData','mailSendNotification','slackSendNotification'))
|
||||
}
|
||||
}
|
237
test/groovy/SonarExecuteTest.groovy
Normal file
237
test/groovy/SonarExecuteTest.groovy
Normal file
@ -0,0 +1,237 @@
|
||||
import static org.hamcrest.Matchers.containsString
|
||||
import static org.hamcrest.Matchers.hasItem
|
||||
import static org.hamcrest.Matchers.is
|
||||
import static org.hamcrest.Matchers.allOf
|
||||
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.RuleChain
|
||||
import org.junit.rules.ExpectedException
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
import util.BasePiperTest
|
||||
import util.JenkinsDockerExecuteRule
|
||||
import util.JenkinsShellCallRule
|
||||
import util.JenkinsReadYamlRule
|
||||
import util.JenkinsStepRule
|
||||
import util.JenkinsLoggingRule
|
||||
import util.Rules
|
||||
|
||||
class SonarExecuteScanTest extends BasePiperTest {
|
||||
private ExpectedException thrown = ExpectedException.none()
|
||||
private JenkinsReadYamlRule readYamlRule = new JenkinsReadYamlRule(this)
|
||||
private JenkinsStepRule jsr = new JenkinsStepRule(this)
|
||||
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
|
||||
private JenkinsShellCallRule jscr = new JenkinsShellCallRule(this)
|
||||
private JenkinsDockerExecuteRule jedr = new JenkinsDockerExecuteRule(this)
|
||||
|
||||
@Rule
|
||||
public RuleChain rules = Rules
|
||||
.getCommonRules(this)
|
||||
.around(readYamlRule)
|
||||
.around(thrown)
|
||||
.around(jedr)
|
||||
.around(jscr)
|
||||
.around(jlr)
|
||||
.around(jsr)
|
||||
|
||||
def sonarInstance
|
||||
|
||||
@Before
|
||||
void init() throws Exception {
|
||||
sonarInstance = null
|
||||
helper.registerAllowedMethod("withSonarQubeEnv", [String.class, Closure.class], { string, closure ->
|
||||
sonarInstance = string
|
||||
return closure()
|
||||
})
|
||||
helper.registerAllowedMethod("unstash", [String.class], { stashInput -> return []})
|
||||
helper.registerAllowedMethod("fileExists", [String.class], { file -> return file })
|
||||
helper.registerAllowedMethod('string', [Map], { m -> m })
|
||||
helper.registerAllowedMethod('withCredentials', [List, Closure], { l, c ->
|
||||
try {
|
||||
binding.setProperty(l[0].variable, 'TOKEN_'+l[0].credentialsId)
|
||||
c()
|
||||
} finally {
|
||||
binding.setProperty(l[0].variable, null)
|
||||
}
|
||||
})
|
||||
nullScript.commonPipelineEnvironment.setArtifactVersion('1.2.3-20180101')
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithDefaults() throws Exception {
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertThat('Sonar instance is not set to the default value', sonarInstance, is('SonarCloud'))
|
||||
assertThat('Sonar project version is not set to the default value', jscr.shell, hasItem(containsString('sonar-scanner -Dsonar.projectVersion=1')))
|
||||
assertThat('Docker image is not set to the default value', jedr.dockerParams.dockerImage, is('maven:3.5-jdk-8'))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithCustomVersion() throws Exception {
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
projectVersion: '2'
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertThat('Sonar project version is not set to the custom value', jscr.shell, hasItem(containsString('sonar-scanner -Dsonar.projectVersion=2')))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithCustomOptions() throws Exception {
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
options: '-Dsonar.host.url=localhost'
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertThat('Sonar options are not set to the custom value', jscr.shell, hasItem(containsString('sonar-scanner -Dsonar.host.url=localhost')))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithCustomOptionsList() throws Exception {
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
options: ['sonar.host.url=localhost']
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertThat('Sonar options are not set to the custom value', jscr.shell, hasItem(containsString('sonar-scanner -Dsonar.host.url=localhost')))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithCustomInstance() throws Exception {
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
instance: 'MySonarInstance'
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertThat('Sonar instance is not set to the custom value', sonarInstance.toString(), is('MySonarInstance'))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithPRHandling() throws Exception {
|
||||
binding.setVariable('env', [
|
||||
'CHANGE_ID': '42',
|
||||
'CHANGE_TARGET': 'master',
|
||||
'BRANCH_NAME': 'feature/anything'
|
||||
])
|
||||
nullScript.commonPipelineEnvironment.setGithubOrg('testOrg')
|
||||
//nullScript.commonPipelineEnvironment.setGithubRepo('testRepo')
|
||||
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
//githubOrg: 'testOrg',
|
||||
githubRepo: 'testRepo'
|
||||
)
|
||||
// asserts
|
||||
assertThat(jscr.shell, hasItem(allOf(
|
||||
containsString('-Dsonar.pullrequest.key=42'),
|
||||
containsString('-Dsonar.pullrequest.base=master'),
|
||||
containsString('-Dsonar.pullrequest.branch=feature/anything'),
|
||||
containsString('-Dsonar.pullrequest.provider=github'),
|
||||
containsString('-Dsonar.pullrequest.github.repository=testOrg/testRepo')
|
||||
)))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithPRHandlingWithoutMandatory() throws Exception {
|
||||
thrown.expect(Exception)
|
||||
thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR githubRepo')
|
||||
|
||||
binding.setVariable('env', ['CHANGE_ID': '42'])
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
githubOrg: 'testOrg'
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertJobStatusFailure()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithLegacyPRHandling() throws Exception {
|
||||
binding.setVariable('env', ['CHANGE_ID': '42'])
|
||||
nullScript.commonPipelineEnvironment.setGithubOrg('testOrg')
|
||||
//nullScript.commonPipelineEnvironment.setGithubRepo('testRepo')
|
||||
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
legacyPRHandling: true,
|
||||
githubTokenCredentialsId: 'githubId',
|
||||
//githubOrg: 'testOrg',
|
||||
githubRepo: 'testRepo'
|
||||
)
|
||||
// asserts
|
||||
assertThat(jscr.shell, hasItem(allOf(
|
||||
containsString('-Dsonar.analysis.mode=preview'),
|
||||
containsString('-Dsonar.github.pullRequest=42'),
|
||||
containsString('-Dsonar.github.oauth=TOKEN_githubId'),
|
||||
containsString('-Dsonar.github.repository=testOrg/testRepo')
|
||||
)))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithLegacyPRHandlingWithoutMandatory() throws Exception {
|
||||
thrown.expect(Exception)
|
||||
thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR githubTokenCredentialsId')
|
||||
|
||||
binding.setVariable('env', ['CHANGE_ID': '42'])
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
legacyPRHandling: true,
|
||||
githubOrg: 'testOrg',
|
||||
githubRepo: 'testRepo'
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertJobStatusFailure()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithSonarAuth() throws Exception {
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
sonarTokenCredentialsId: 'githubId'
|
||||
)
|
||||
// asserts
|
||||
assertThat(jscr.shell, hasItem(containsString('-Dsonar.login=TOKEN_githubId')))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithSonarCloudOrganization() throws Exception {
|
||||
jsr.step.sonarExecuteScan(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
organization: 'TestOrg-github'
|
||||
)
|
||||
|
||||
// asserts
|
||||
assertThat(jscr.shell, hasItem(containsString('-Dsonar.organization=TestOrg-github')))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
}
|
@ -41,7 +41,8 @@ class JenkinsSetupRule implements TestRule {
|
||||
JOB_NAME : 'p',
|
||||
BUILD_NUMBER: '1',
|
||||
BUILD_URL : 'http://build.url',
|
||||
BRANCH_NAME: 'master'
|
||||
BRANCH_NAME: 'master',
|
||||
WORKSPACE: 'any/path'
|
||||
])
|
||||
|
||||
base.evaluate()
|
||||
|
@ -236,14 +236,12 @@ private deploy(script, utils, Map configuration, NeoCommandHelper neoCommandHelp
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
||||
if (dockerImage) {
|
||||
echo "Error while deploying to SAP Cloud Platform. Here are the neo.sh logs:"
|
||||
try {
|
||||
sh "cat logs/neo/*"
|
||||
} catch(Exception e) {
|
||||
echo "Unable to provide the logs."
|
||||
ex.addSuppressed(e)
|
||||
}
|
||||
echo "Error while deploying to SAP Cloud Platform. Here are the neo.sh logs:"
|
||||
try {
|
||||
sh "cat logs/neo/*"
|
||||
} catch(Exception e) {
|
||||
echo "Unable to provide the logs."
|
||||
ex.addSuppressed(e)
|
||||
}
|
||||
throw ex
|
||||
}
|
||||
|
@ -55,11 +55,12 @@ void call(Map parameters = [:]) {
|
||||
piperInitRunStageConfiguration script: script, stageConfigResource: config.stageConfigResource
|
||||
|
||||
if (env.BRANCH_NAME == config.productiveBranch) {
|
||||
if (parameters.script.commonPipelineEnvironment.configuration.runStep?.get('Init')?.slackSendNotification) {
|
||||
slackSendNotification script: script, message: "STARTED: Job <${env.BUILD_URL}|${URLDecoder.decode(env.JOB_NAME, java.nio.charset.StandardCharsets.UTF_8.name())} ${env.BUILD_DISPLAY_NAME}>", color: 'WARNING'
|
||||
}
|
||||
artifactSetVersion script: script
|
||||
}
|
||||
|
||||
pipelineStashFilesBeforeBuild script: script
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,12 @@ void call(Map parameters = [:]) {
|
||||
utils.pushToSWA([step: STEP_NAME], config)
|
||||
|
||||
influxWriteData script: script
|
||||
|
||||
if(env.BRANCH_NAME == parameters.script.commonPipelineEnvironment.getStepConfiguration('', '').productiveBranch) {
|
||||
if(parameters.script.commonPipelineEnvironment.configuration.runStep?.get('Post Actions')?.slackSendNotification) {
|
||||
slackSendNotification script: parameters.script
|
||||
}
|
||||
}
|
||||
mailSendNotification script: script
|
||||
}
|
||||
}
|
||||
|
193
vars/sonarExecuteScan.groovy
Normal file
193
vars/sonarExecuteScan.groovy
Normal file
@ -0,0 +1,193 @@
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.Utils
|
||||
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
import groovy.transform.Field
|
||||
import groovy.text.SimpleTemplateEngine
|
||||
|
||||
@Field String STEP_NAME = getClass().getName()
|
||||
|
||||
@Field Set GENERAL_CONFIG_KEYS = [
|
||||
/**
|
||||
* Pull-Request voting only:
|
||||
* The URL to the Github API. see https://docs.sonarqube.org/display/PLUG/GitHub+Plugin#GitHubPlugin-Usage
|
||||
* deprecated: only supported in LTS / < 7.2
|
||||
*/
|
||||
'githubApiUrl',
|
||||
/**
|
||||
* Pull-Request voting only:
|
||||
* The Github organization.
|
||||
* @default: `commonPipelineEnvironment.getGithubOrg()`
|
||||
*/
|
||||
'githubOrg',
|
||||
/**
|
||||
* Pull-Request voting only:
|
||||
* The Github repository.
|
||||
* @default: `commonPipelineEnvironment.getGithubRepo()`
|
||||
*/
|
||||
'githubRepo',
|
||||
/**
|
||||
* Pull-Request voting only:
|
||||
* The Jenkins credentialId for a Github token. It is needed to report findings back to the pull-request.
|
||||
* deprecated: only supported in LTS / < 7.2
|
||||
* @possibleValues Jenkins credential id
|
||||
*/
|
||||
'githubTokenCredentialsId',
|
||||
/**
|
||||
* The Jenkins credentialsId for a SonarQube token. It is needed for non-anonymous analysis runs. see https://sonarcloud.io/account/security
|
||||
* @possibleValues Jenkins credential id
|
||||
*/
|
||||
'sonarTokenCredentialsId',
|
||||
]
|
||||
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
|
||||
/**
|
||||
* Pull-Request voting only:
|
||||
* Disables the pull-request decoration with inline comments.
|
||||
* deprecated: only supported in LTS / < 7.2
|
||||
* @possibleValues `true`, `false`
|
||||
*/
|
||||
'disableInlineComments',
|
||||
/**
|
||||
* Name of the docker image that should be used. If empty, Docker is not used and the command is executed directly on the Jenkins system.
|
||||
* see dockerExecute
|
||||
*/
|
||||
'dockerImage',
|
||||
/**
|
||||
* The name of the SonarQube instance defined in the Jenkins settings.
|
||||
*/
|
||||
'instance',
|
||||
/**
|
||||
* Pull-Request voting only:
|
||||
* Activates the pull-request handling using the [GitHub Plugin](https://docs.sonarqube.org/display/PLUG/GitHub+Plugin) (deprecated).
|
||||
* deprecated: only supported in LTS / < 7.2
|
||||
* @possibleValues `true`, `false`
|
||||
*/
|
||||
'legacyPRHandling',
|
||||
/**
|
||||
* A list of options which are passed to the `sonar-scanner`.
|
||||
*/
|
||||
'options',
|
||||
/**
|
||||
* Organization that the project will be assigned to in SonarCloud.io.
|
||||
*/
|
||||
'organization',
|
||||
/**
|
||||
* The project version that is reported to SonarQube.
|
||||
* @default: major number of `commonPipelineEnvironment.getArtifactVersion()`
|
||||
*/
|
||||
'projectVersion'
|
||||
])
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
|
||||
|
||||
/**
|
||||
* The step executes the [sonar-scanner](https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) cli command to scan the defined sources and publish the results to a SonarQube instance.
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
|
||||
def utils = parameters.juStabUtils ?: new Utils()
|
||||
def script = checkScript(this, parameters) ?: this
|
||||
// load default & individual configuration
|
||||
Map configuration = ConfigurationHelper.newInstance(this)
|
||||
.loadStepDefaults()
|
||||
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
|
||||
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
|
||||
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, GENERAL_CONFIG_KEYS)
|
||||
.mixin(parameters, PARAMETER_KEYS)
|
||||
.addIfEmpty('projectVersion', script.commonPipelineEnvironment.getArtifactVersion()?.tokenize('.')?.get(0))
|
||||
.addIfEmpty('githubOrg', script.commonPipelineEnvironment.getGithubOrg())
|
||||
.addIfEmpty('githubRepo', script.commonPipelineEnvironment.getGithubRepo())
|
||||
// check mandatory parameters
|
||||
.withMandatoryProperty('githubTokenCredentialsId', null, { config -> config.legacyPRHandling && isPullRequest() })
|
||||
.withMandatoryProperty('githubOrg', null, { isPullRequest() })
|
||||
.withMandatoryProperty('githubRepo', null, { isPullRequest() })
|
||||
.use()
|
||||
|
||||
if(configuration.options instanceof String)
|
||||
configuration.options = [].plus(configuration.options)
|
||||
|
||||
def worker = { config ->
|
||||
withSonarQubeEnv(config.instance) {
|
||||
loadSonarScanner(config)
|
||||
|
||||
if(config.organization) config.options.add("sonar.organization=${config.organization}")
|
||||
if(config.projectVersion) config.options.add("sonar.projectVersion=${config.projectVersion}")
|
||||
// prefix options
|
||||
config.options = config.options.collect { it.startsWith('-D') ? it : "-D${it}" }
|
||||
|
||||
sh "PATH=\$PATH:${env.WORKSPACE}/.sonar-scanner/bin sonar-scanner ${config.options.join(' ')}"
|
||||
}
|
||||
}
|
||||
|
||||
if(configuration.sonarTokenCredentialsId){
|
||||
def workerForSonarAuth = worker
|
||||
worker = { config ->
|
||||
withCredentials([string(
|
||||
credentialsId: config.sonarTokenCredentialsId,
|
||||
variable: 'SONAR_TOKEN'
|
||||
)]){
|
||||
config.options.add("sonar.login=$SONAR_TOKEN")
|
||||
workerForSonarAuth(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isPullRequest()){
|
||||
def workerForGithubAuth = worker
|
||||
worker = { config ->
|
||||
if(config.legacyPRHandling) {
|
||||
withCredentials([string(
|
||||
credentialsId: config.githubTokenCredentialsId,
|
||||
variable: 'GITHUB_TOKEN'
|
||||
)]){
|
||||
// support for https://docs.sonarqube.org/display/PLUG/GitHub+Plugin
|
||||
config.options.add('sonar.analysis.mode=preview')
|
||||
config.options.add("sonar.github.oauth=$GITHUB_TOKEN")
|
||||
config.options.add("sonar.github.pullRequest=${env.CHANGE_ID}")
|
||||
config.options.add("sonar.github.repository=${config.githubOrg}/${config.githubRepo}")
|
||||
if(config.githubApiUrl) config.options.add("sonar.github.endpoint=${config.githubApiUrl}")
|
||||
if(config.disableInlineComments) config.options.add("sonar.github.disableInlineComments=${config.disableInlineComments}")
|
||||
workerForGithubAuth(config)
|
||||
}
|
||||
} else {
|
||||
// see https://sonarcloud.io/documentation/analysis/pull-request/
|
||||
config.options.add("sonar.pullrequest.key=${env.CHANGE_ID}")
|
||||
config.options.add("sonar.pullrequest.base=${env.CHANGE_TARGET}")
|
||||
config.options.add("sonar.pullrequest.branch=${env.BRANCH_NAME}")
|
||||
config.options.add("sonar.pullrequest.provider=${config.pullRequestProvider}")
|
||||
switch(config.pullRequestProvider){
|
||||
case 'github':
|
||||
config.options.add("sonar.pullrequest.github.repository=${config.githubOrg}/${config.githubRepo}")
|
||||
break;
|
||||
default: error "Pull-Request provider '${config.pullRequestProvider}' is not supported!"
|
||||
}
|
||||
workerForGithubAuth(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dockerExecute(
|
||||
script: script,
|
||||
dockerImage: configuration.dockerImage
|
||||
){
|
||||
worker(configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean isPullRequest(){
|
||||
return env.CHANGE_ID
|
||||
}
|
||||
|
||||
private void loadSonarScanner(config){
|
||||
def filename = new File(config.sonarScannerDownloadUrl).getName()
|
||||
def foldername = filename.replace('.zip', '').replace('cli-', '')
|
||||
|
||||
sh """
|
||||
curl --remote-name --remote-header-name --location --silent --show-error ${config.sonarScannerDownloadUrl}
|
||||
unzip -q ${filename}
|
||||
mv ${foldername} .sonar-scanner
|
||||
"""
|
||||
}
|
Loading…
Reference in New Issue
Block a user