Dependency Graph Viewer Plugin einrichten

Wenn es mal unübersichtlich mit den Jobs in Jenkins wird, kann man mit dem Dependency Graph Viewer Plugin ein wenig Licht in die Sache bringen. Vor allem dann, wenn es darum geht zu sehen, welcher Job welchen anderen Job startet. Wenn z.B. der Job Bauen den Job Unittests aufruft, lässt sich das dem Dependency Graph Viewer Plugin gut visualisieren.

Ein Beispielgraph produziert durch den Dependency Graph Viewer Plugin

Zuerst muss man natürlich das Plugin in Jenkins installieren. Ich gehe jetzt davon aus, dass klar ist wie man in Jenkins ein Plugin installiert.

Als ich nach der Installation versucht hatte, einen Graph zu erstellen, bekam ich stattdessen in der Browser-Konsole eine Fehlermeldung dieser Art. Es gab wohl auch andere, die davon betroffen waren.

TypeError: div.firstChild is null hudson-behavior.js:862:21
    onSuccess http://192.168.0.26:8080/static/b568631b/scripts/hudson-behavior.js:862
    respondToReadyState http://192.168.0.26:8080/static/b568631b/scripts/prototype.js:1657
    onStateChange http://192.168.0.26:8080/static/b568631b/scripts/prototype.js:1600
    bind http://192.168.0.26:8080/static/b568631b/scripts/prototype.js:414

Die Lösung für das Problem besteht aus zwei Teilen:

1. Sicherstellen, dass graphviz aus dem Betriebssystem installiert ist. Mein Jenkins lief auf einem CentOS-System, da reichte es aus graphviz mit dem Befehl

sudo yum install graphviz

zu installieren. Wichtig ist hierbei, dass man nach der Installation das Programm dot finden kann:

sh-4.2# which dot
/usr/bin/dot

2. In den Systemeinstellungen muss der Pfad zu dem Programm dot gesetzt sein.

Hier kann es aber auch sein, dass man auch keinen Pfad setzen muss. Im Zweifel einfach mal testen. Wichtig ist jedoch, dass der Pfad zum dot Programm vollständig ist und hier nicht nur der Pfad gesetzt wird, in dem sich das Programm dot befindet.

Weitere mögliche Quellen:

ERROR: [WS-CLEANUP] Cannot delete workspace: Remote call on … failed

Vor kurzem hatte ich einen Job in Jenkins, der die Einstellung hatte den Arbeitsbereich auf einem Jenkins-Slave zu löschen bevor der Job fortführen sollte:

Auf einmal bekam ich jedoch regelmäßig Fehlermeldungen dieser Art:

[WS-CLEANUP] Deleting project workspace…
[WS-CLEANUP] Deferred wipeout is used…
ERROR: [WS-CLEANUP] Cannot delete workspace: Remote call on … failed
ERROR: Cannot delete workspace: Remote call on … failed

Die Lösung in diesem Fall war die: Ich musste den Jenkins-Slave erst einmal richtig trennen

um ihn anschließend wieder zu verbinden.

Im Grunde habe ich den Slave-Agenten neu gestartet. Seitdem trat der Fehler nicht mehr auf.

Caused by: java.lang.NoClassDefFoundError: com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider

Ich hatte kürzlich Jenkins frisch aufgesetzt und die empfohlenen Plugins installiert. Als ich ein Multibranch Pipeline Projekt erstellt hatte und konfigurieren wollte, ging nichts mehr. Ich konnte nichts konfigurieren und bekam zudem diese Fehlermeldung zu Gesicht:

org.apache.commons.jelly.JellyTagException: jar:file:/root/.jenkins/war/WEB-INF/lib/jenkins-core-2.176-SNAPSHOT.jar!/lib/hudson/actions.jelly:39:70: <st:include> com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider at org.apache.commons.jelly.impl.TagScript.handleException(TagScript.java:745) at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:289) at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:161) at org.apache.commons.jelly.tags.core.ForEachTag.doTag(ForEachTag.java:150) at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:269)
...
Caused by: java.lang.NoClassDefFoundError: com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider at java.lang.Class.getDeclaringClass0(Native Method) at java.lang.Class.getDeclaringClass(Class.java:1235) at java.lang.Class.getEnclosingClass(Class.java:1277) at com.cloudbees.plugins.credentials.CredentialsStore.<init>(CredentialsStore.java:102)
...
Caused: javax.servlet.ServletException at org.kohsuke.stapler.jelly.JellyClassTearOff.serveIndexJelly(JellyClassTearOff.java:119) at org.kohsuke.stapler.jelly.JellyFacet.handleIndexRequest(JellyFacet.java:146) at org.kohsuke.stapler.IndexViewDispatcher.dispatch(IndexViewDispatcher.java:30) at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:747)

Die wichtige Fehlermeldung ist hier fett hervorgehoben. Ursache für dieses Problem ist, dass ein Plugin nicht installiert gewesen ist: Das Cloudbees Credentials Plugin.

Erste Schritte mit BitBucket und Webhooks

In BitBucket lassen sich sogenannte Webhooks für ein Repository erstellen. Diese Webhooks melden dann dem CI Server, wenn sich was im Repository geändert hat. Ich habe meine ersten Schritte mit BitBucket und den Webhooks gemacht. Diese möchte ich hier aufschreiben.

Ein Webhook in BitBucket zu erstellen, sollte recht einfach sein. Als erstes muss man in die Einstellungen von dem gewünschten Repository gehen, in dem man die Webhooks einrichten möchte:

Dort müsste ein Button “Add Webhook” auftauchen:

Wenn man auf “Add Webhook” klickt, dann sollte ein neues Formular auftauchen, in dem man die gewünschten Einstellungen setzen kann:

Der “Title” ist hierbei frei wählbar. Unter “URL” sollte man in etwa folgendes eingeben (natürlich angepasst):

http://<url-of-jenkins>/git/notifyCommit?url=<url-of-repository>

Man sollte hier darauf achten, dass der Teil <url-of-repository> sowohl im Webhook als auch in dem entsprechendem Job in Jenkins gleich sind.

Nun muss man noch sicher stellen, dass auf Jenkinsseite alle Einstellungen korrekt sind. Wie schon erwähnt, sollte die Repository-URL gleich sein. Im Job von Jenkins sollte zu dem noch ein Haken bei Source Code Management abfragen gesetzt sein. Einen Zeitplan muss man hier jedoch nicht unbedingt setzen:


Setzt man den Haken nicht, wird kein Job gestartet und in BitBucket sieht man dann Meldungen wie diese:

No git jobs using repository: https://bitbucket.org/some-repo... and branches:  No Git consumers using SCM API plugin for: https://bitbucket.org/some-repo...

Ich hoffe, mein Post hat euch gefallen / geholfen.

Jenkins Pipeline: Werte von einem Job zum anderen übergeben

Manchmal möchte man Werte zwischen zwei Jobs weiter geben. Dies kann man mit Jenkins Pipeline recht einfach bewerkstelligen. Dazu müssen beide Jobs richtig konfiguriert sein.

Der erste Job muss die Möglichkeit haben einen zweiten Job mit Parametern zu starten. Wie hier in diesem Jenkinsfile:

pipeline {
agent any
stages {
stage("Build") {
steps {
sh "echo First job"
}
}

stage("Trigger") {
steps {
build job: 'Pipe 2', parameters: [string(name: 'VAR2', value: "somevalue2")], wait: false
}
}
}
}

Der zweite Job (hier “Pipe 2” genannt) muss die Möglichkeit haben, Parameters zu empfangen:

pipeline {
agent any
parameters {
string(name: 'VAR2', defaultValue: 'TESTING', description: '')
}
stages {
stage('Build') {
steps {
echo env.VAR2
sh "printenv"
}
}
}
}

Der Jenkinsslave und die Javaversion

Wie sich mal wieder herausgestellt hat, ist die Javaversion auf einer Windows-Slave-Maschine von großer Bedeutung. Auf einer Windows-Slave-Maschine wollte ich eine Batch-Datei ausführen, die wiederum ein Powershell-Skript aufgerufen hat. Während des Durchlaufs bekam ich jedoch diese Fehlermeldung in Jenkins:

Import-Module : Could not load file or assembly 'file:///C:\Program Files\WindowsPowerShell\Modules\Msonline\1.1.183.17\Microsoft.Online.Administration.Automation.PSModule.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format.

Das seltsame daran war jedoch, dass dieses Skript in der Eingabeaufforderung von Windows auf derselben Maschine ohne Probleme lief. Mit Jenkins bekam ich jedoch diese Fehlermeldung. Wie sich herausgestellt hat, war auf der Slave-Maschine eine x86-Version von Java installiert. Diese habe ich dann deinstalliert und die entsprechende x64-Version installiert. Danach musste man nur noch den Slave-Agenten neu starten und die Fehlermeldung war beim nächsten Bau verschwunden.

Quellen:

Jenkins master – Zu wenig Speicherplatz

Mit der Zeit kann es vorkommen, dass der frei verfügbare Speicherplatz auf dem Server auf dem Jenkins läuft, immer kleiner wird. Das kann unter Anderem auch an Jenkins selbst liegen.

In diesem Post möchte ich ein paar Hilfestellungen geben, wie man dieses Problem lösen und auch vorbeugen kann. Ich werde in diesem Post von meiner Jenkins Installation ausgehen, die auf einem Ubuntu-Server installiert ist. Auf anderen Linux- oder Windows-Servern muss man die vorgestellten Strategien jedoch anpassen.

Speicherhungrige Jobs finden

Auf meinem Ubuntu-Server ist Jenkins unter dem Pfad /var/lib/jenkins installiert. Unter diesem Ordner gibt es einen Ordner namens jobs, in dem es wiederum weitere Ordner gibt. Jeder dieser Ordner ist nach dem jeweiligen Job in Jenkins benannt. Wenn man also einen Job namens First Job hat, dann findet man unter jobs einen Ordner, der auch First Job heißt.

Mit dem Kommandos

cd /var/lib/jenkins/jobs

du -h –max-depth=1 | sort -hr

bekommt man nun eine Auflistung aller Ordner in jobs und die Größe aller Dateien zusammen vom jeweiligen Ordner.

Auf diese Weise kann man erkennen, welche Jobs den meisten Speicherplatz belegen. In meinem Fall ist das jedoch noch kein Problem. Will man jedoch für mehr Speicherplatz sorgen gib, kann es helfen, die Anzahl der Builds zu limitieren.

Anzahl der Builds limitieren

Standardmäßig speichert Jenkins jeden Build ab, den ein Job je ausgeführt hat. Insbesondere auch dann, wenn man anfängt, Artefakte zu archivieren (eine Post-build Aktion), kann der verfügbare Speicherplatz je nach Projekt sehr schnell klein werden. Wenn man aber die Anzahl der Builds limitiert, werden alte Builds von Jenkins automatisch gelöscht und es wird regelmäßig Speicherplatz wieder frei gelegt.

Um die Anzahl der Builds zu limitieren, muss man in einer Job-Konfiguration unter General einen Haken vor Discard old builds setzen und je nach belieben Werte einsetzen:

Anschließend das Speichern nicht vergessen 😉

Ein Jenkins Plugin installieren

Erst durch die vielen Plugins wird Jenkins zu dem was es ist: Ein sehr mächtiges Werkzeug. Doch wie installiert man ein Plugin in Jenkins? In diesem Post will ich aufzeigen, wie man in Jenkins Plugins installieren kann.

Manage Plugins

Der übliche Weg geht über den Link Manage Jenkins.

Wenn man auf den Link Manage Jenkins klickt, taucht eine neue Seite mit einer Reihe von Buttons. Einer davon hat den Titel Manage Plugins.

Wenn man auf diesen Knopf drückt, kommt man auf die Seite, auf der man Plugin installieren kann.

Auf dieser Seite muss man in den Reiter Available wechseln. Dort wird eine Reihe von installierbaren Plugins aufgelistet. Jetzt muss man dort nach dem gewünschten Plugin suchen. Dabei kann man das Suchfeld rechts oben zur Hilfe nehmen.

Hat man das gewünschte Plugin gefunden, setzt man einen Haken links neben dem Namen des Plugins. In meinem Beispiel will ich jetzt das Plugin Pipeline installieren.

Im Browser unten müsste sich jetzt ein Knopf namens Download now and install after restart befinden. Diesen muss man drücken. Anschließend startet man Jenkins neu.

 

Jobs triggern Jobs in Jenkins – Parameterized Plugin

Neben den Boardmitteln von Jenkins, weitere Jobs zu triggern, gibt es einige Plugins, die dasselbe erledigen und dabei mehr Einstellungen anbieten können. In diesem Post geht es um das Plugin namens Parameterized Plugin. Dieses Plugin erlaubt es, in einem Job oder am Ende eines Jobs weitere Jobs zu starten und dazu noch Parameter zu übergeben. Ich nehme jetzt an, dass der Leser/die Leserin das Plugin Parameterized Plugin schon installiert hat.

Job vor Job starten

Es gibt Fälle, da möchte man einen Job laufen lassen, bevor der eigentliche Job gestartet wird. Mit dem Parameterized Plugin  geht das folgendermaßen: In der Konfiguration des eigentlichen Jobs geht man in die Build-Sektion und fügt dort einen neuen Build-Schritt hinzu: Trigger/call builds on other projects.

Nun müsste ein neuer Build-Schritt erscheinen. Diesen muss man eventuell nach oben schieben, je nachdem, wie man es haben möchte und entsprechend konfigurieren (siehe nächstes Bild). Second Job ist in dem Fall ein zweiter Job, den ich in diesem Beispiel starten möchte, bevor der eigentliche Build-Prozess von dem aktuellen Job gestartet wird.

Nun kann man weiter unten auf Save drücken und es einfach mal ausprobieren. Dabei muss man darauf achten, dass die entsprechenden Knoten (master / slaves) genügend Slots haben. Ansonsten könnte es passieren, dass ein Job einen anderen blockiert.

Job nach Job starten

Genauso wie man einen Job vor einem Job starten kann (siehe das Unterkapitel weiter oben), kann man auch einen Job nach einem anderen Job starten. In diesem Fall fügt man in der Liste der Post-build-Aktionen eine weitere Aktion hinzu: Trigger parameterized build on other projects.

Nun müsste ein neuer Bereich in den Post-build-Aktionen aufgetaucht sein. Diesen gilt es nun anzupassen und dann mit einem Klick auf Save zu speichern.

Jobs triggern Jobs in Jenkins

In diesem Post möchte ich euch zeigen, wie man einen zweiten Job startet, wenn der erste fertig ist. Das lässt sich mit den Boardmitteln von Jenkins recht einfach realisieren. Dazu muss man in den Post-build actions den Punkt Build other projects auswählen und dann den Namen des anderen Jobs eintragen.

In diesem Fall habe ich zu Testzwecken einen zweiten Job namens Second Job erstellt, der gestartet wird, wenn der erste erfolgreich fertig geworden ist.

Wie man in dem obigen Bild sieht, kann man einstellen, wann der zweite Job Second Job gestartet werden soll. Dies kann geschehen, wenn der erste Job erfolgreich war (Trigger only if build is stable), oder wenn das Ergebnis vom ersten Job instabil ist (Trigger even if the build is unstable) oder auch dann, wenn der erste Job fehlgeschlagen ist (Trigger even if the build fails). Ich habe das jetzt einfach mal auf Trigger only if build is stable eingestellt.

Ist alles eingerichtet, sieht man das auch später in der Liste der Downstream Projects:

Nun kann man einen Testlauf durchführen und den ersten Job starten. Nach dem Ende des ersten Jobs sollte automatisch der zweite gestartet werden (je nachdem, wie das Ergebnis des ersten Jobs ist und welche Einstellung man gewählt hat).