Sonarqube quality gate not sending webhook to jenkins

15,137

Solution 1

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

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

Solution 3

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

Solution 4

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.

Solution 5

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;
                    }
                }
            }
        }
    }
Share:
15,137
Admin
Author by

Admin

Updated on June 07, 2022

Comments

  • Admin
    Admin almost 2 years

    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