Quality Gates in Sonar mit Jenkins Pipelines nutzen

Es ist in Sonar möglich “quality gates” zu definieren. Damit kann die Qualität des Codes (oder des neuen Codes) gegenüber bestimmten Schwellwerten (Testabdeckung, Anzahl der Majors, etc.) überwacht werden (siehe https://docs.sonarqube.org/display/SONAR/Quality+Gates).

Wenn man den Sonar-Lauf von Jenkins aus startet, dann wäre es wünschenswert, dass das Ergebnis des Quality-Gates in das Ergebnis des Jenkins-Laufs übernommen wird. Glücklicherweise ist das mit dem neuen Pipeline-Konzept recht einfach.

Unsere Umgebung sieht wie folgt aus:

  • Sonar Version 5.6.6
  • Jenkins Version 2.19.4
  • Maven Version 3.3.9
  • Java Version 8

Damit das Konzept umgesetzt werden kann, müssen einige Voraussetzungen erfüllt sein:

  • Folgende Plugins müssen im Jenkins installiert sein: Http Request Plugin und Pipeline Utility Steps Plugin
  • Ein Quality-Gate muss in Sonar definiert und dem zu analysierenden Projekt zugeweisen sein
  • Falls der Zugriff auf Sonar nur angemeldeten Benutzern erlaubt ist, müssen Credentials für den Sonar-Zugriff in Jenkins definiert sein

Anmerkung: Das Skript basiert auf dem Beispiel https://stackoverflow.com/a/45345264. Folgende Anpassungen waren notwendig:

  • Der Sonar-Job läuft als einfacher ‘mvn sonar:sonar’ Aufruf (Zeile 9)
  • Der Pfad zur Datei report-task.txt ist falsch und wurde angepasst (Zeile 12)
  • Credentials (ID der Zugangsdaten) für den Sonar-Zugriff anpassen (Zeile 25)

 

 1 withSonarQubeEnv('qm') {
 2    withMaven(
 3            maven: 'maven-3',
 4            mavenOpts: '-Xmx1024m',
 5           jdk: 'jdk1.8')
 6   {
 7       // Run the maven build
 8       sh "mvn -Pit-tests clean install"
 9       sh "mvn sonar:sonar"
10       echo "\u2713 success"
11   }
12   sh "cat target/sonar/report-task.txt"
13   defprops = readProperties  file: 'target/sonar/report-task.txt'
14   defsonarServerUrl=props['serverUrl']
15   defceTaskUrl= props['ceTaskUrl']
16   defceTask
17   timeout(time: 1, unit: 'MINUTES') {
18       waitUntil {
19           defresponse = httpRequest ceTaskUrl
20           ceTask = readJSON text: response.content
21           echo ceTask.toString()
22           return"SUCCESS".equals(ceTask["task"]["status"])
23       }
24   }
25   defresponse = httpRequest url : sonarServerUrl + "/api/qualitygates/project_status?analysisId="+ ceTask["task"]["analysisId"], authentication: 'ci-user'
26   defqualitygate =  readJSON text: response.content
27   echo qualitygate.toString()
28   if("ERROR".equals(qualitygate["projectStatus"]["status"])) {
29       error  "Quality Gate failure"
30   }
31 }

 

Das Konzept: Zuerst läuft ein Maven-Build inklusive der Integrationstests (Zeile 8) und dann der Sonar-Aufruf (Zeile 9). Nach dem Sonarlauf hinterlegt Sonar eine Datei report-task.txt. Mit den darin enthaltenen Informationen und dem Sonar-REST-API kann man die “Compute Engine Task” Informationen abrufen (Zeile 14-24). Darin enthalten ist die TaskId des Sonar-Jobs. Damit lassen sich die Quality-Gate-Informationen des Sonar-Laufs abrufen (Zeile 25) und auswerten (Zeile 26-30). Im aktuellen Beispiel schlägt der Build fehl, wenn das Quality-Gate nicht erreicht wurde. Zwischendurch werden Werte zur (Debug-)Informationszwecken ausgegeben (Zeile 12 und 27).

Wenn kein Quality-Gate existiert, dann liefert der Aufruf in Zeile 26 nur den Wert {"projectStatus":{"status":"NONE","conditions":[],"periods":[]}} und damit bringt die nachfolgende Auswertung keinen Fehler. Alternativ könnte man prüfen, ob überhaupt ein Quality-Gate definiert wurde ("conditions" darf dann nicht leer sein) und darauf reagieren.

Wie man sieht, ist es relativ einfach, eine Rückmeldung von Sonar innerhalb von Jenkins zu erreichen.