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 defceTask17 timeout(time: 1, unit: 'MINUTES') {18 waitUntil {19 defresponse = httpRequest ceTaskUrl20 ceTask = readJSON text: response.content21 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.content27 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.
