A simple sonar quality gates (groovy) script to Break the CI Build in Jenkins

Recently, we migrated to Sonar 6.4. The migration was smooth and everything worked as expected (or that what we thought at that moment). After few days, we noticed that many of our build start failing, and the console shows:

quality.gates.jenkins.plugin.QGException: Expected status 200, got: 404. Response: {"errors":[\{"msg":"Unknown url : /api/events"}]}

The quality gates plugin was not working anymore, and a quick google search shows that we were not the only ones facing this issue. We've tried some workarounds but none of them worked. By the end of the day, we've to choose between 2 options: Downgrade sonar version (Nah) or make our own quality gates breaker (Let's think about it! How hard would it be)

A simple quality gate breaker script using Groovy

The first step toward making our own quality gates breaker is to describe its workflow. Thanks to SonarQube team, They've done it before, that we can resume in:

  1. Call the /api/ce/task?id=${ceTaskId} web service to retrieve analysisId. You can get the ceTaskId from /report-task.txt under your working directory.
  2. If the CE Task Status is PENDING or IN_PROGRESS, the script should wait, and repeat step 1
  3. If the CE Task Status is SUCCESS, we save the analysisId and proceed to step 5
  4. If the CE Task Status is FAILED or CANCELED, we break the build
  5. Call the /api/qualitygates/project_status?analysisId=${analysisId} web service to check the status of the quality gate
  6. If the quality gate status is OK or WARN, allow the build to pass. If the quality gate status is ERROR, we break the build.

The first version of this script looks like this:

        @Grapes(
            @Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1')
        )
        import static groovyx.net.http.ContentType.TEXT

        def taskClient = new groovyx.net.http.HTTPBuilder('http://<SONAR_URL>/api/ce/task?id=TASK_ID')
        taskClient.setHeaders(Accept: 'application/json')

        def taskResponse = taskClient.get(contentType: TEXT)
        def taskSlurper = new groovy.json.JsonSlurper().parse(taskResponse)
        def status=taskSlurper.task.status

        while ( status == "PENDING" || status == "IN_PROGRESS" ) {
        println "waiting for sonar results"
        sleep(1000)
        }
              assert status != "CANCELED" : "Build fail because sonar project is CANCELED"
              assert status != "FAILED" : "Build fail because sonar project is FAILED"
              qualitygatesClient = new groovyx.net.http.HTTPBuilder('http://<SONAR_URL>//api/qualitygates/project_status?analysisId='+taskSlurper.task.analysisId)
              qualitygatesClient.setHeaders(Accept: 'application/json')
              qualitygatesResponse = qualitygatesClient.get(contentType: TEXT)
              def qualitygates= new groovy.json.JsonSlurper().parse(qualitygatesResponse)
              assert qualitygates.projectStatus.status != "ERROR" : "Build fail because sonar project status is not ok"
              println "Huraaaah! You made it :) Sonar Results are good"

Configuring Jenkins and sonar

After that we need to configure Sonar Quality gates thresholds and Jenkins to run the script.

For setting up Sonar quality policy, log in to sonar, go to quality gates menu, and configure values that suites your need:

As for Jenkins, you need to download the groovy plugin, and add a step on your build configuration to run the script:

Voila! Below a screenshot from our Jenkins build:

The script is available on github. OF course if you've any suggestion feel free to comment below, or make a PR ;)