Running SonarQube scanner - Java/TypeScript - jenkins

Checkout of front end & back end code in multiple folders within jenkin's ${WORKSPACE}
, as shown below
Frontend code is written in Angular(TypeScript) and built using npm
Backend code is written in Java and built using gradlew
Referring documentation for SonarQube scanner with Jenkins, here. I got the below piece of code to run SonarQube scanner for multi-language(angular & java) static code analysis
node {
stage('SCM') {
git 'https://github.com/foo/bar.git'
}
stage('SonarQube analysis') {
// requires SonarQube Scanner 2.8+
def scannerHome = tool 'SonarQube Scanner 2.8';
withSonarQubeEnv('My SonarQube Server') {
sh "${scannerHome}/bin/sonar-scanner"
}
}
}
As per below screenshot, below is the sonar scanner installation in jenkins:
1) Does def scannerHome = tool 'abc_install'; grab the SonarQube scanner configured in Jenkins?
2) Does sh "${scannerHome}/bin/sonar-scanner" perform static code analysis for both TypeScript & Java? in front-end-code & backend-code folder

Please see answers:
1) Of course. In Jenkins you can configure many SonarQube scanners with different versions, and with construction def scannerHome = tool '<scanner name, configured in Jenkins>' you may grab any scanner your code need
2) Yes, it will. But, I'd recommend to split backend and frontend and specify language for each part. Also, I'd remove folders with with '#tmp' from static code scan. Please see list of parameters that can be added to scanner here: https://docs.sonarqube.org/latest/analysis/analysis-parameters/
Small example for backend:
${scannerHome}/bin/sonar-scanner \
-Dsonar.projectKey=project-${ENVIRONMENT} \
-Dsonar.sources=portal,common \
-Dsonar.java.binaries=portal,common \
-Dsonar.java.libraries=/**/*.jar \
-Dsonar.exclusions=portal/src/test/**,portal/src/intest/** \
-Dsonar.coverage.jacoco.xmlReportPaths=portal/build/reports/jacoco/test/jacocoTestReport.xml

Related

'.' is not recognized as an internal or external command for Gradle command in Jenkins when gradlew script is executed

I try to run SonarQube analysis for a Gradle project in a Jenkins Pipeline using the following code:
stage('SonarQube') {
withGradle {
withSonarQubeEnv('SonarQube Env') {
bat "./gradlew sonarqube"
}
}
}
The Gradle plugin is installed in Jenkins but I am getting the following error:
05:15:05 D:\*\*\*\*\*\*>./gradlew sonarqube
05:15:05 '.' is not recognized as an internal or external command,
Two things are incorrect in your code. On Windows machines you have to:
use backslashes instead of slashes in paths (./command → .\command)
execute script written for Windows (gradlew is a Unix script, gradlew.bat is a Windows script)
This code should work:
stage('SonarQube') {
withGradle {
withSonarQubeEnv('SonarQube Env') {
bat '.\\gradlew.bat sonarqube'
}
}
}
Gradle Wtapper by default is provided with two script gardlew and gradlew.bat. If your project doesn't have the gradlew.bat file, execute on your Unix machine ./gradlew wrapper. The missing file will be generated.
Btw. You don't need the Jenkins Gradle plugin, when you use Gradlew Wrapper. The plugin is required when you want to provide Gradle installations for jobs, example:
stage('SonarQube') {
withGradle {
withSonarQubeEnv('SonarQube Env') {
bat "${tool(name: 'toolId', type: 'gradle')}\\bin\\gradle.bat sonarqube"
}
}
}
toolId must much the identifiers used in the Jenkins Global Tool Configuration, examples: gradle-6.X, gradle-6.8.3 etc.

How to send credentials to a powershell script in a jenkins pipeline?

When executing the following code in a Jenkins pipeline, a "The following steps that have been detected may have insecure interpolation of sensitive variables" warning is being added to the build, with a link to https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#string-interpolation with explanation.
powershell script: """
\$ErrorActionPreference = "Stop"
cd "${WORKSPACE}\\MyDirectory"
& .\\myScript.ps1 -user "${creds_USR}" -passw "${creds_PSW}"
"""
I've already tried to change it as described in the link above, but then the variables don't seem to be replaced anymore.
powershell script: '''
\$ErrorActionPreference = \"Stop\"
cd \"$WORKSPACE\\MyDirectory\"
& .\\myScript.ps1 -user \"$creds_USR\" -passw \"$creds_PSW\"
'''
Would somebody know a working solution for this please?
Presumably you have a block like this that's generating those values:
environment {
creds = credentials('some-credentials')
}
So your build environment has those variables available to Powershell. Rather than interpolating the string that constitutes the Powershell script, then, just write the script to pull the data from the environment.
powershell script: '''\
$ErrorActionPreference = "Stop"
cd "$Env:WORKSPACE\MyDirectory"
& .\myScript.ps1 -user "$Env:creds_USR" -passw "$Env:creds_PSW"
'''

SonarQube Scanner fails in a Jenkins pipeline due to command not found

I'd like to run SonarQube Scanner from a Jenkins pipeline and I followed the documentation.
Regarding the error, it seems that the scanner is present but some commands are not found. My jenkins instance runs in a docker.
Jenkins version : 2.46.1
SonarQube Scanner : 2.6.1
+ /var/lib/jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/SonarQube_Scanner/bin/sonar-scanner
/var/lib/jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/SonarQube_Scanner/bin/sonar-scanner: line 56: which: command not found
/var/lib/jenkins/tools/hudson.plugins.sonar.SonarRunnerInstallation/SonarQube_Scanner/bin/sonar-scanner: line 66: exec: : not found
In the sonar-scanner script, there is this block
if [ -n "$JAVA_HOME" ]
then
java_cmd="$JAVA_HOME/bin/java"
else
java_cmd="$(which java)"
fi
And given that my JAVA_HOME was unset, the script called which and the command is not installed inside my container.
As a workaround, I set the env variable JAVA_HOME.
Make sure the PATH is complete, or check if resetting it is enough
def sonarqubeScannerHome = tool name: 'SonarQubeScanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation'
withEnv(["PATH=/usr/bin: ..."]) {
// Your call to Sonar
sh "${sonarqubeScannerHome}/bin/sonar-scanner -e -Dsonar.host.url=..."
}
I used the setup from "Execute SonarQube Scanner within Jenkins 2 Pipeline", but with Sonar 2.5, there is an official support of Jenkins pipeline:
def scannerHome = tool 'SonarQube Scanner 2.8';
withEnv(["PATH=/usr/bin: ..."]) {
withSonarQubeEnv('My SonarQube Server') {
sh "${scannerHome}/bin/sonar-scanner"
}
}

Using waitForQualityGate in a Jenkins declarative pipeline

The following SonarQube (6.3) analysis stage in a declarative pipeline in Jenkins 2.50 is failing with this error in the console log: http://pastebin.com/t2ja23vC. More specifically:
SonarQube installation defined in this job (SonarGate) does not match any configured installation. Number of installations that can be configured: 1.
Update: after changing "SonarQube" to "SonarGate" in the Jenkins settings (under SonarQube servers, so it'll match the Jenkinsfile), I get a different error: http://pastebin.com/HZZ6fY6V
java.lang.IllegalStateException: Unable to get SonarQube task id and/or server name. Please use the 'withSonarQubeEnv' wrapper to run your analysis.
The stage is a modification of the example from the SonarQube docs: https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Jenkins#AnalyzingwithSonarQubeScannerforJenkins-AnalyzinginaJenkinspipeline
stage ("SonarQube analysis") {
steps {
script {
STAGE_NAME = "SonarQube analysis"
if (BRANCH_NAME == "develop") {
echo "In 'develop' branch, don't analyze."
}
else { // this is a PR build, run sonar analysis
withSonarQubeEnv("SonarGate") {
sh "../../../sonar-scanner-2.9.0.670/bin/sonar-scanner"
}
}
}
}
}
stage ("SonarQube Gatekeeper") {
steps {
script {
STAGE_NAME = "SonarQube Gatekeeper"
if (BRANCH_NAME == "develop") {
echo "In 'develop' branch, skip."
}
else { // this is a PR build, fail on threshold spill
def qualitygate = waitForQualityGate()
if (qualitygate.status != "OK") {
error "Pipeline aborted due to quality gate coverage failure: ${qualitygate.status}"
}
}
}
}
}
I also created a webhook, sonarqube-webhook, with the URL http://****/sonarqube-webhook/. Should it be like that, or http://****/sonarqube/sonarqube-webhook? To access the server dashboard I use http://****/sonarqube.
In SonarQube's Quality Gates section I created a new quality gate:
I am not sure if the setting in SonarGate is correct. I do use jenkins-mocha to generate an lcov.info file that is used in Sonar to generate the coverage data.
Perhaps the quality gate setting is the wrong setting to do? The end result is to fail the job in Jenkins if coverage % is not met.
Finally, I am not sure if the following configurations in the Jenkins system configuration are at all required:
And
(It's 9000 not 900... cut text in the screen shot)
The SonarQube Jenkins plugin scans the build output for two specific lines, which it uses to get the SonarQube report task properties and project URL. If your invocation of sonar-scanner does not output these lines, the waitForQualityGate() call won't have the task ID to look them up. So you will have to figure out the correct settings to make it more verbose.
See the extractSonarProjectURLFromLogs and extractReportTask methods in the SonarUtils class of the plugin to understand how they work:
ANALYSIS SUCCESSFUL, you can browse <project URL> is used to add a link to the badge (in the build history)
Working dir: <dir with report-task.txt> is used to pass the task ID to the waitForQualityGate step
This was discovered to be a bug in the SonarQube scanner for Jenkins, when using a Jenkins slave for jobs (if the job is run on the master, it'd work). You can read more here: https://jira.sonarsource.com/browse/SONARJNKNS-282
I have tested this using a test build of v2.61 of the scanner plug-in and found it working.
The solution is to upgrade to v2.61 when released.
This stage will then work:
stage ("SonarQube analysis") {
steps {
withSonarQubeEnv('SonarQube') {
sh "../../../sonar-scanner-2.9.0.670/bin/sonar-scanner"
}
def qualitygate = waitForQualityGate()
if (qualitygate.status != "OK") {
error "Pipeline aborted due to quality gate coverage failure: ${qualitygate.status}"
}
}
}
If you're running SonarCube in a docker container check that the memory isn't exhausted. We were maxing out. Which seemed to be the issue.

Execute SonarQube Scanner within Jenkins 2 Pipeline

I want to execute a "SonarQube Scanner" Step within my Jenkins 2.x Pipeline.
When I try to create a sample groovy within the pipeline-syntax I only get a groovy script of the following format:
step <object of type hudson.plugins.sonar.SonarRunnerBuilder>
Does anyone know what is the correct Step Syntax? E.g. Publish JUnit Report looks like
step([$class: 'JUnitResultArchiver', testResults: ''])
I use the following Versions:
Jenkins 2.11
SonarQube Scanner 2.6.1
SonarQube Plugin 2.4.1
I think I got it.
First you have to retrieve your SonarQube Scanner Tool
def sonarqubeScannerHome = tool name: 'SonarQubeScanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation'
Then you can call sonar-scanner via Shell:
sh "${sonarqubeScannerHome}/bin/sonar-scanner -e -Dsonar.host.url=..."
env.sonarHome= tool name: 'scanner-2.4', type: 'hudson.plugins.sonar.SonarRunnerInstallation'
withSonarQubeEnv('sonar.installation') { // from SonarQube servers > name
sh "${sonarHome}/bin/sonar-runner -Dsonar.host.url=${SONAR_HOST_URL} -Dsonar.login=${SONAR_AUTH_TOKEN} -Dsonar.projectName=xxx -Dsonar.projectVersion=xxx -Dsonar.projectKey=xxx -Dsonar.sources=."
}
You can, instead, just provide the full path to ur sonar-runner. As shown in the below snippet.
def runSonarScan(sonar_url){
withEnv(['SONAR_HOST=' + sonar_url]) {
sh '''
$/opt/sonarqube/sonar-runner-2.4/bin/sonar-runner -e -Dsonar.host.url=${SONAR_HOST}
'''
}
}
If you have specific sonar properties add them as a sonar-project.properties file as shown here Sonar Project Properties

Resources