7

Within my Jenkins Pipeline I need to react on the SonarQube Quality Gate. Is there an easier way to achieve this but looking in the Sonar-Scanner log for the result page (e.g. https://mysonarserver/sonar/api/ce/task?id=xxxx) and parse the JSON Result from there?

I use Jenkins 2.30 and SonarQube 5.3

Thanks in advance

Christoph Forster
  • 1,728
  • 4
  • 27
  • 39

4 Answers4

8

Based on Vincent's answer, and using Pipeline utility steps, here's my updated version that worked for me (using sonarscanner report file) :

   withSonarQubeEnv('SONAR 6.4') {
                    sh "${scannerHome}/bin/sonar-scanner"
                    sh "cat .scannerwork/report-task.txt"
                    def props = readProperties  file: '.scannerwork/report-task.txt'
                    echo "properties=${props}"
                    def sonarServerUrl=props['serverUrl']
                    def ceTaskUrl= props['ceTaskUrl']
                    def ceTask
                    timeout(time: 1, unit: 'MINUTES') {
                        waitUntil {
                            def response = httpRequest ceTaskUrl
                            ceTask = readJSON text: response.content
                            echo ceTask.toString()
                            return "SUCCESS".equals(ceTask["task"]["status"])
                        }
                    }
                    def response2 = httpRequest url : sonarServerUrl + "/api/qualitygates/project_status?analysisId=" + ceTask["task"]["analysisId"], authentication: 'jenkins_scanner'
                    def qualitygate =  readJSON text: response2.content
                    echo qualitygate.toString()
                    if ("ERROR".equals(qualitygate["projectStatus"]["status"])) {
                        error  "Quality Gate failure"
                    }
                }

Please note the use of a Jenkins Credentials (authentication: 'jenkins_scanner') to retrieve the quality gate in Sonar being auhtenticated.

Tibo
  • 246
  • 2
  • 5
  • 1
    Hi @tibo, Could you please let me know how did you authenticate to sonarqube using "jenkins_scanner" ? – Jerald Sabu M Nov 21 '17 at 10:39
  • 1
    I got it, it is coming from http request plugin. https://stackoverflow.com/questions/41571090/basic-auth-with-jenkins-http-request-plugin Thanks a lot, this answer helped me to implement notifications on quality gate failure. – Jerald Sabu M Nov 21 '17 at 14:31
8

Using SonarQube Scanner for Jenkins 2.8.1 the solution is available out of the Box:

stage('SonarQube analysis') {
    withSonarQubeEnv('My SonarQube Server') {
        sh 'mvn clean package sonar:sonar'
    } // SonarQube taskId is automatically attached to the pipeline context
  }
}
stage("Quality Gate"){
    timeout(time: 1, unit: 'HOURS') { // 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}"
    }
  }
}
Christoph Forster
  • 1,728
  • 4
  • 27
  • 39
  • this solution works perfectly. Only point to be added here is, we need to configure the jenkins webhook on sonar for this to work. – pvpkiran Oct 08 '19 at 15:21
  • what happens when you call waitForQualityGate()? does jenkins reach out to the sonarqube server and check its status? if you dont have webhooks configured can this still be used to poll sonarqube by running waitForQualityGate() several times to poll ? – red888 Mar 05 '20 at 16:44
  • @red888 - I assume it's not working without Webhook. See here: https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-jenkins/ – Christoph Forster Mar 06 '20 at 06:50
5

Scan first:

node("sonar") {
      deleteDir()
      unstash 'sources'
      def scannerHome = tool 'sonar-scanner'; 
      withSonarQubeEnv('sonarqube-rec') {
          withEnv(["JAVA_HOME=${ tool 'JDK_8.0' }", "PATH+MAVEN=${tool 'M325'}/bin:${env.JAVA_HOME}/bin"]) {        
           // requires SonarQube Scanner for Maven 3.2+
           sh '''
             mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.2:sonar
             echo "SONAR_AUTH_TOKEN=$SONAR_AUTH_TOKEN" >> target/sonar/report-task.txt
           '''
           stash includes: "target/sonar/report-task.txt", name: 'sonar-report-task'
          }
      }
    }

then check the quality gate:

    stage("Quality Gate"){
    node("sonar") {
        deleteDir()
        unstash 'sonar-report-task'
        def props = utils.getProperties("target/sonar/report-task.txt")
        echo "properties=${props}"
        def sonarServerUrl=props.getProperty('serverUrl')
        def ceTaskUrl= props.getProperty('ceTaskUrl')
        def ceTask
        def URL url = new URL(ceTaskUrl)
          timeout(time: 1, unit: 'MINUTES') {
            waitUntil {
              ceTask = utils.jsonParse(url)
              echo ceTask.toString()
              return "SUCCESS".equals(ceTask["task"]["status"])
            }
          }
          url = new URL(sonarServerUrl + "/api/qualitygates/project_status?analysisId=" + ceTask["task"]["analysisId"] )
          def qualitygate =  utils.jsonParse(url)
          echo qualitygate.toString()
          if ("ERROR".equals(qualitygate["projectStatus"]["status"])) {
            error  "Quality Gate failure"
          }
   }
}
2

I used ".sonar/report-task.txt" to retrieve the ceTaskUrl - Then I used Pipeline Shared Libraries and wrote my own Pipeline Function to retrieve the quality gate.

http://mySonarQube.com:9001/api/ce/task?id="ceTaskUrl"

Parse "task.analysisId"

Parse quality-gates from http://mySonarQube.com:9001/api/qualitygates/project_status?analysisId="task.analysisId"

Christoph Forster
  • 1,728
  • 4
  • 27
  • 39