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
def
props = readProperties file:
'target/sonar/report-task.txt'
14
def
sonarServerUrl=props[
'serverUrl'
]
15
def
ceTaskUrl= props[
'ceTaskUrl'
]
16
def
ceTask
17
timeout(time:
1
, unit:
'MINUTES'
) {
18
waitUntil {
19
def
response = httpRequest ceTaskUrl
20
ceTask = readJSON text: response.content
21
echo ceTask.toString()
22
return
"SUCCESS"
.equals(ceTask[
"task"
][
"status"
])
23
}
24
}
25
def
response = httpRequest url : sonarServerUrl +
"/api/qualitygates/project_status?analysisId="
+ ceTask[
"task"
][
"analysisId"
], authentication:
'ci-user'
26
def
qualitygate = 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.