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

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"
}
}

Related

Jenkins build failed due to command not being recognized

I have this build error saying pandoc command is not recognize, when I build my pipeline on Jenkins :
But when I run the exact same command using cmd.exe from the same repository it works perfectly :
So what's wrong here, my command pandoc is well installed and can perfectly be used from cmd.exe, why doesn't it works from Jenkins ?
Here is my Jenkins code (the part causing the error is in the "Build" stage):
pipeline {
agent any
stages {
stage('Prerequisites') {
steps {
//bat 'RMDIR C:\\wamp64\\www\\html\\doc'
bat 'MKDIR C:\\wamp64\\www\\html\\doc'
}
}
stage('Build') {
steps {
bat 'pandoc -s C:\\wamp64\\www\\index.md -o C:\\wamp64\\www\\index.html'
bat 'pandoc -s C:\\wamp64\\www\\index.md -o C:\\wamp64\\www\\index.docx'
}
}
stage('Deploy') {
steps {
bat 'COPY C:\\wamp64\\www\\index.html COPY C:\\wamp64\\www\\html\\index.html'
bat 'COPY C:\\wamp64\\www\\index.docx COPY C:\\wamp64\\www\\html\\doc\\index.docx'
}
}
}
}
Thanks for helping.
Jenkins doesn't automatically take your Windows (path) environment variables. Instead, what you need to do is to go to Jenkins -> Configure System -> Global properties -> Environment variables and add a new variable called Path. For the value, set $Path, and your path variables should start getting registered.
The issue has been discussed extensively in this question.

'.' 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.

Maven pipeline fails to find JDK

I have a problem running a simple Java Maven pipeline. The used maven command fails using the expected JDK for an unknown reason.
freshly installed Jenkins running from the docker image jenkinsci/blueocean:latest
configured Oracle JDK 9 and Maven 3.5.4 at the Jenkins Tools settings pane
Jenkinsfile content:
pipeline {
agent any
tools {
jdk 'java9'
maven 'Maven3.5'
}
stages {
stage ('Initialize') {
steps {
sh '''
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
echo "JAVA_HOME = ${JAVA_HOME}"
'''
}
}
stage ('Build') {
steps {
sh 'java -version'
sh 'mvn --version'
}
}
}
}
Output of the "Initialize" stage script
PATH = /var/jenkins_home/tools/hudson.model.JDK/java9/bin:/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5/bin:/var/jenkins_home/tools/hudson.model.JDK/java9/bin:/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin
M2_HOME = /var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5
JAVA_HOME = /var/jenkins_home/tools/hudson.model.JDK/java9
This looks valid to me. M2_HOME and JAVA_HOME point to the expected path of the Jenkins tools.
Output of the "Build" "java -version" script
+ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (IcedTea 3.10.0) (Alpine 8.191.12-r0)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
This seems to be the installed Java of the Jenkins docker host system
Failure output of the "Build" "mvn -version" script:
mvn --version
/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5/bin/mvn: exec: line 191: /var/jenkins_home/tools/hudson.model.JDK/java9/bin/java: not found
script returned exit code 127
If I bash into the Jenkins docker container, I find the java bin at the mentioned path.
Where is my mistake? Why can't Maven find the Java?
Is it a permission problem? Jenkins docker container uses a docker volume:
-v jenkins-data:/var/jenkins_home.
Best,
Lars
Not sure tools + docker in Jenkins Pipeline is working so good.
See: https://issues.jenkins-ci.org/browse/JENKINS-36159
Only way so far I've managed to get this to work was by mounting the docker node's tools directory into the docker slave.
e.g.
agent { docker
args '-v $HOME/tools:/var/lib/jenkins/tools'
stage { step {
sh "${MAVEN_HOME}/bin/mvn -version"
EDIT: Just found this too: https://issues.jenkins-ci.org/browse/JENKINS-48050
You don't need both tools. It is enough with Maven tool. It includes Java. Your pipeline should be:
pipeline {
agent any
tools {
maven 'Maven3.5'
}
stages {
stage ('Initialize') {
steps {
sh '''
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
echo "JAVA_HOME = ${JAVA_HOME}"
'''
}
}
stage ('Build') {
steps {
sh 'java -version'
sh 'mvn --version'
}
}
}
}
And you can delete Java Tool in Jenkins configuration tool.
This problem occurs when you're using an alpine based docker image for jenkins and your jdk is glibc based. You can solve this in two ways:
Use a jdk that is musl based. You can find them on adoptium by filtering out the OS as Alpine Linux.
Use a non-alpine based docker image.

Running SonarQube Scanner on a Jenkins remote slave

I have a Docker container running Jenkins (2.150.1) and another Docker container running SonarQube (7.4). Jenkins is using the SonarQube Scanner for Jenkins plugin and the scanning is done on the Jenkins container. The Jenkinsfile for the project looks like this:
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'building...'
}
}
stage('Test') {
steps {
echo 'testing...'
withSonarQubeEnv ('SonarQube') {
sh '/var/jenkins_home/sonar-scanner/sonar-scanner-3.2.0.1227-linux/bin/sonar-scanner'
}
echo 'really finished testing2'
}
}
stage("Quality Gate") {
steps {
timeout(time: 1, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
stage('Deployment') {
steps {
echo 'deploying...'
}
}
}
}
To get the scanning to work as part of a Jenkins pipeline job, I manually installed sonar-scanner on the Jenkins container by downloading the zip file and unzipping it to: /var/jenkins_home/sonar-scanner/sonar-scanner-3.2.0.1227-linux
This is working well, but I want to improve it by:
taking out the harcoded path to sonar-scanner from my Jenkinsfile
specify a non local location of sonar-scanner because I now need to run the scan on another VM/container instead of on the Jenkins container
I tried using Manage Jenkins > Global Tool Configuration > SonarQube Scanner and updated my Jenkinsfile to use SONAR_RUNNER_HOME instead of the hard coded path, but that didn't work and I got an error that sonar-scanner can't be found.
In Manage Jenkins > Global Tool Configuration > SonarQube Scanner check install automatically.
Then go to Manage Jenkins > Configure System and add the following
The Name should be the same as the parameter in the line in your Jenkinsfile: withSonarQubeEnv('SonarQube')

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