1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00
sap-jenkins-library/vars/sonarExecuteScan.groovy
Christopher Fenner 14e7ef23b4
fix: sonarExecuteScan: safeguard unstash of git metadata (#976)
* unstash .git folder only if not present, ignore missing stashes

* fix: negate condition

* Update sonarExecuteScan.groovy
2019-11-13 12:55:02 +01:00

242 lines
9.6 KiB
Groovy

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.GStringTemplateEngine
import java.nio.charset.StandardCharsets
@Field String STEP_NAME = getClass().getName()
@Field Set GENERAL_CONFIG_KEYS = [
/**
* Pull-Request voting only:
* The URL to the Github API. see [GitHub plugin docs](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 [SonarQube docs](https://docs.sonarqube.org/latest/user-guide/user-token/)
* @possibleValues Jenkins credential id
*/
'sonarTokenCredentialsId',
/**
* Print more detailed information into the log.
* @possibleValues `true`, `false`
*/
'verbose'
]
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
/**
* List containing download links of custom TLS certificates. This is required to ensure trusted connections to instances with custom certificates.
*/
'customTlsCertificateLinks',
/**
* 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](dockerExecute.md)
*/
'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 ->
try {
withSonarQubeEnv(config.instance) {
loadSonarScanner(config)
loadCertificates(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(' ')}"
}
} finally {
sh 'rm -rf .sonar-scanner .certificates .scannerwork'
}
}
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.CHANGE_BRANCH}")
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
){
if(!script.fileExists('.git')) {
utils.unstash('git')
}
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
"""
}
private void loadCertificates(Map config) {
String certificateFolder = '.certificates/'
List wgetOptions = [
"--directory-prefix ${certificateFolder}"
]
List keytoolOptions = [
'-import',
'-noprompt',
'-storepass changeit',
'-keystore .sonar-scanner/jre/lib/security/cacerts'
]
if (config.customTlsCertificateLinks){
if(config.verbose){
wgetOptions.push('--verbose')
keytoolOptions.push('-v')
}else{
wgetOptions.push('--no-verbose')
}
config.customTlsCertificateLinks.each { url ->
def filename = new File(url).getName()
filename = URLDecoder.decode(filename, StandardCharsets.UTF_8.name())
sh "wget ${wgetOptions.join(' ')} ${url}"
sh "keytool ${keytoolOptions.join(' ')} -alias '${filename}' -file '${certificateFolder}${filename}'"
}
}
}