6

I configure Jenkins to work with sonarqube scanner. The scan are working fine. The jenkins pipeline is working and I don't have any isssue in the jenkins log.

SonarQube Scanner 3.0.3.778 Jenkins: 2.70 SonarQube Scanner for Jenkins plugin: 2.6.1

I use this code:

    stage('SonarQube analysis') {
        sh 'sed -ie "s|_PROJECT_|${PROJECT_CODE}|g" $WORKSPACE/_pipeline/sonar-project.properties'
        // requires SonarQube Scanner 3.0+
        def scannerHome = '/opt/sonar/bin/sonar-scanner';
        withSonarQubeEnv('mscodeanalysis') {
            sh "${scannerHome}/bin/sonar-scanner -Dproject.settings=$WORKSPACE/_pipeline/sonar-project.properties"
        }
    }
    }
    }
}
    }
    // No need to occupy a node
    stage("Quality Gate"){
        timeout(time: 15, unit: 'MINUTES') { // Just in case something goes wrong, pipeline will be killed after a timeout
        def qg = waitForQualityGate() // Reuse taskId previously collected by withSonarQubeEnv
            if (qg.status != 'OK') {
                error "Pipeline aborted due to quality gate failure: ${qg.status}"
            }
        }
    }

My problem come from Quality Gate. It never POST the json payload to jenkins. I don't see a json entry inside jenkins log. But I know the connection between jenkins and sonarqube server is working because I was able to send a POST using curl from the sonarqube VM.

Here the jenkins job output:

Timeout set to expire in 15 min
[Pipeline] {
[Pipeline] waitForQualityGate
Checking status of SonarQube task 'AV3irVJXpvBxXXNJYZkd' on server 'mscodeanalysis'
SonarQube task 'AV3irVJXpvBxXXNJYZkd' status is 'PENDING'
Cancelling nested steps due to timeout

Here is my payload that never reach jenkins pipeline: url: http://sonar-server:9000/api/ce/task?id=AV3irVJXpvBxXXNJYZkd

{"task":{"organization":"default-organization","id":"AV3irVJXpvBxXXNJYZkd","type":"REPORT","componentId":"AV3hrJeCfL_nrF2072FH","componentKey":"POOL-003","componentName":"POOL-003","componentQualifier":"TRK","analysisId":"AV3irVkZszLEB6PsCK9X","status":"SUCCESS","submittedAt":"2017-08-14T21:36:35+0000","submitterLogin":"jenkins","startedAt":"2017-08-14T21:36:37+0000","executedAt":"2017-08-14T21:36:38+0000","executionTimeMs":650,"logs":false,"hasScannerContext":true}}

I can't insert image but the Quality gate is Pass and the analysis task is success.

Let me know if I need to include more information. Thank you

Marc
  • 67
  • 1
  • 1
  • 3
  • To verify: you _did_ configure a webhook to post back to Jenkins at the end of server-side processing, right? – G. Ann - SonarSource Team Aug 15 '17 at 13:51
  • Yes, I configure the webhook on this page: http://sonarqube-servert:9000/settings?category=webhooks Put nameL Jenkins and url: https://jenkins-int.domain.com/sonarqube-webhook/ – Marc Aug 15 '17 at 14:35
  • And your logs show the webhooks being fired? Also, do you have a proxy or firewall between the two boxes? – G. Ann - SonarSource Team Aug 15 '17 at 14:44
  • In which log can I see this? There is nothing in ce.log I do have a firewall between box. But curl -H "Content-Type: application/json" -X POST -d "PAYLOAD I already past" https://jenkins-int.domain.comt/sonarqube-webhook/ Reach jenkins server. I can see the POST in jenkins log. Also after the jenkins job run. I am able to see: SonarQube Quality Gate TEST-003 OK server-side processing: Success On jenkins job page – Marc Aug 15 '17 at 15:05

8 Answers8

4

The issue could be that Jenkins is using https with self-signed certificate. Then solution is:

  1. Generate truststore for SonarQube:

    keytool -import -trustcacerts -alias jenkins-host-name -file cert.crt -keystore sonarqube.jks
    

    keystore passw: password

    Where cert.crt - is certificate used for ssl for jenkins, jenkins-host-name - is a hostname of jenkins in the docker network (which is used in webhook)

  2. Add truststore to SonarQube Dockerfile:

    FROM sonarqube
    COPY sonarqube.jks /var/sonar_cert/
    COPY sonar.properties /opt/sonarqube/conf/sonar.properties
    
  3. Update sonar.properties

    sonar.ce.javaAdditionalOpts=-Djavax.net.ssl.trustStore=/var/sonar_cert/sonarqube.jks -Djavax.net.ssl.trustStorePassword=password
    

Then if you have a correct user and password for Jenkins provided in webhook URL everything should work.

Tried: Jenkins 2.107.2, SonarQube 7.1

heroin
  • 2,148
  • 1
  • 23
  • 32
  • After doing it, I get the error HTTP 401, and log message from ce.log: Failed to send webhook url=my-jenkins-ip/sonarqube-webhook/ | message=the trustAnchors parameter must be non-empty – Bill Hoo May 15 '18 at 02:45
  • The error "trustAnchors parameter must be non-empty" is indicates that the sonarqube.jks file is not found, and I finally figured out I should use absolute path with -Djavax.net.ssl.trustStore setting. Thanks. – Bill Hoo May 15 '18 at 11:58
  • do you meet this error when configuring with self-signed certs? Failed to send webhook 'Jenkins CI' | url=https://1.2.3.4:5678/sonarqube-webhook/ | message=Hostname 1.2.3.4 not verified: – Bill Hoo May 15 '18 at 12:06
  • You need to use domain name of Jenkins server (if there is no, then you may create it by editing ``/etc/hosts`` on SonarQube server), ip addresses are not ok when usings SSL certificates. – heroin May 16 '18 at 07:47
2

Here is a quick example of what we did to resolve this issue:

SonarQube randomly hangs at "pending" state. Telling it to retry refreshes it. We set it to 10 seconds in this example

maxRetry = 200
forloop (i=0; i<maxRetry; i++){
    try {
        timeout(time: 10, unit: 'SECONDS') {
            waitForQualityGate()
        }
    } catch(Exception e) {
        if (i == maxRetry-1) {
            throw e
        }
    }
}
Katone Vi
  • 1,010
  • 1
  • 8
  • 12
2

Was surprised to find that @Katone Vi's answer worked so well. Based on their answer we added a quick exit on success and used the DSL for the original request:

    stage('SonarQube') {
      steps {
        withSonarQubeEnv('SonarQube') {
          sh """
            ${scannerHome}/bin/sonar-scanner -Dsonar.projectKey=XXX_${env.STAGE}_lambda
          """
        }

        script {
          Integer waitSeconds = 10
          Integer timeOutMinutes = 10
          Integer maxRetry = (timeOutMinutes * 60) / waitSeconds as Integer
          for (Integer i = 0; i < maxRetry; i++) {
            try {
              timeout(time: waitSeconds, unit: 'SECONDS') {
                def qg = waitForQualityGate()
                if (qg.status != 'OK') {
                  error "Sonar quality gate status: ${qg.status}"
                } else {
                  i = maxRetry
                }
              }
            } catch (Throwable e) {
              if (i == maxRetry - 1) {
                throw e
              }
            }
          }
        }
      }
    }
Typhlosaurus
  • 1,528
  • 12
  • 14
2

If you have configured SonarQube to use a HTTP(S) proxy, make sure that your jenkins is either reachable through the proxy or is configured as a "non-proxy host". This can be done with the http.nonProxyHosts property or HTTP_NONPROXYHOSTS environment variable. See also the documentation for further information and syntax.

Corubba
  • 2,229
  • 24
  • 30
1

If you are using Jenkinsfile, this is workaround:

define creadentials:

 environment { 
  CRED = credentials('jenkins_user_pass') 
 }

then use:

stage("Quality Gate") {
    steps {
         script {
                while(true){
                    sh "sleep 2"
                    def url="http://jenkinsURL/job/${env.JOB_NAME.replaceAll('/','/job/')}/lastBuild/consoleText";
                    def sonarId = sh script: "wget -qO- --content-on-error --no-proxy --auth-no-challenge --http-user=${CRED_USR} --http-password=${CRED_PSW} '${url}'  | grep 'More about the report processing' | head -n1 ",returnStdout:true
                    sonarId = sonarId.substring(sonarId.indexOf("=")+1)
                    echo "sonarId ${sonarId}"
                    def sonarUrl = "http://jenkinsURL/sonar/api/ce/task?id=${sonarId}"
                    def sonarStatus = sh script: "wget -qO- '${sonarUrl}' --no-proxy --content-on-error | jq -r '.task' | jq -r '.status' ",returnStdout:true
                    echo "Sonar status ... ${sonarStatus}"
                    if(sonarStatus.trim() == "SUCCESS"){
                        echo "BREAK";
                        break;
                    }
                    if(sonarStatus.trim() == "FAILED "){
                        echo "FAILED"
                        currentBuild.result = 'FAILED'
                        break;
                    }
                }
            }
        }
    }
user1722245
  • 2,065
  • 1
  • 18
  • 31
1

I have faced similar issue, while the quality Gate back-end activities in Sonar server takes less than 20 sec to complete its analysis.But quality gate fail/success response from sonar-webhook in jenkins job take lot of time and stuck.

 stage('Sonar:QG') {
            steps {
                **sleep(10)  /* Added 10 sec sleep that was suggested in few places*/**
                script{
                    timeout(time: 10, unit: 'MINUTES') {
                        def qg = waitForQualityGate abortPipeline: true
                        if (qg.status != 'OK') {
                            echo "Status: ${qg.status}"
                            error "Pipeline aborted due to quality gate failure: ${qg.status}"
                        }
                    }
                }
            }
        }

Essentially check below thing:- Webhook is configured in sonar or not :- SonarQube -> Administration -> Webhooks http://:/sonarqube-webhook/

or Use localhost in place of IP in http://locahlhost:port/sonarqube-webhook/ solves issue in my case.

Vishy Anand
  • 93
  • 1
  • 10
0

I'm made more simple decision but it work a same

stage("Quality gate") {
      steps {
        retry(3){
            waitForQualityGate abortPipeline: true
          }

      }
    }
Vlad Gor
  • 71
  • 1
  • 4
-1

Adding a sh 'sleep 10' between stage('SonarQube analysis') AND stage("Quality Gate") fix the issue. Now the jenkins job receive

Checking status of SonarQube task 'AV3rHxhp3io6giaQF_OA' on server 'sonarserver'
SonarQube task 'AV3rHxhp3io6giaQF_OA' status is 'SUCCESS'
SonarQube task 'AV3rHxhp3io6giaQF_OA' completed. Quality gate is 'OK'
Marc
  • 67
  • 1
  • 1
  • 3
  • 2
    For me this is not a proof that problem is fixed. This may simply be that the asynchronous task on SonarQube side take less than 10s to complete. So you receive 'SUCCESS' not because of the webhook, but simply because task is already completed when waitForQualityGate starts. – Julien H. - SonarSource Team Nov 13 '17 at 12:07
  • 2
    sorry, This is not a solution. The result of this "workaround" is, that JOB WILL FREEZE UP! I studied source code from https://github.com/jenkinsci/sonarqube-plugin/blob/master/src/main/java/org/sonarsource/scanner/jenkins/pipeline/WaitForQualityGateStep.java. There are two step. (1) try to call sonar qube directly by sonar/api/ce/task?id=xxxxx. (2) If the result is not SUCCESS then they will create async task which contains listener SonarQubeWebHook. But still, ISSUE, that sonar doesnt call Jenkins! – user1722245 Mar 21 '18 at 15:37