25
.
4
.
2017

Automatisiertes Releasemanagement mit Jenkins

Upload von Artefakten als GitHub Release Assets

EINLEITUNG

Für meine kleineren OpenSource Projekte nutze ich immer Travis CI welchen ich auch sehr mag, da er über die Datei ‘.travis.yml’ eine schöne und einfache Möglichkeit bietet seinen Build zu beschreiben.

Bei meiner aktuelle OpenSource Spielerei namens Kartoffelstampf habe ich mich entschloßen mehrere GitHub Projekte zu verwenden und bspw. die Build Artefakte von ‘Kartoffelstamp-Client’ automatisiert als Asset zum GitHub Release hochzuladen. Ein Release Asset sieht auf GitHub wie folgt aus.

Release Asset
‍Release Asset

Das geschieht dabei ganz automatisch über einige Deploy-Anweisungen in der ‘.travis.yml’.

github:0bc34c8e44430557889ad28d732030cf

Wenn wir uns obiges Statement durchlesen dann lesen wir das unscheinbare ‘on: tags: true’. Was bedeutet das? Es bedeutet, dass wir nur bei einen Git Tag unsere Artefakte als GitHub Release Asset gepublished haben wollen.

 

GEHT DAS AUCH MIT JENKINS?

Da ich zwar Travis CI generell sehr toll finde, so findet wiederum mein Geldbeutel Jenkins besonders toll. Die Idee war geboren Ich möchte einen Jenkins Job der Branches und Tags baut und bei Tags die Artefakte als GitHub Release Asset published. Das ganze möchte ich für mein Customfield Editor Plugin für Atlassian JIRA® nun in Jenkins umsetzen.

 

 

GITHUB PLUGIN ODER ‘BUG-SCHLEUDER’

Bisher habe ich immer das vom Jenkins GitHub Plugin bereitgestellte Webhook feature als Build-Auslöser Einstellung in meinen Jobs verwendet.

GitHub Plugin Build Auslöser
‍GitHub Plugin Build Auslöser

Und jetzt kommt das Schlimme. Wenn ich nun einen Tag gepushed habe hat er ein völlig anderes Tag gebaut!

Das Jenkins GitHub Plugin und sein ‘Build when a change is pushed to GitHub’ oder wie es seit neuestem heißt ‘GitHub hook trigger for GITScm polling’ sind total kaputt! Ja das ist ein schwerwiegender Vorwurf, aber nach Stunden des Reverse-Engineerings und ausprobierens mehrerer Möglichkeiten stehe ich dazu.

Falls Sie dieses Feature auch bereits verwendet haben, so sollte Ihnen diese URL bekannt vorkommen. Diese stellt man in GitHub als Webhook URL für den Push-Event ein.

https://ciuser:pass@jenkins.foo/github-webhook/

Ich pushe also wie ein bekloppter Tags in der Form von:

shell:git tag -a customfield-editor-plugin-1.3.0-rc19 -m "rel 1.3.0-rc19"
shell:git push origin customfield-editor-plugin-1.3.0-rc19

Und es wird immer der falsche Tag gebaut. Was geschieht im Hintergrund? Also generell mag man denken, dass das GitHub Plugin den im Webhook Request enthaltenen JSON-Request-Body parsed und von dort die Information extrahiert, welcher Tag oder Branch nun zu bauen ist. Irgendwie tut es das aber nicht und führt stattdessen einen fehlgeleiteten ‘git fetch’ aus, der ihn dann zur Erkentniss bringt, dass ich doch das Tag ‘customfield-editor-plugin-1.0’ gebaut haben möchte, was über 4 Jahre alt und auch nicht Teil des JSON-Request-Body ist.

Gut haken wir es ab, ich wollte nur klarstellen: Das GitHub-Plugin Webhook Feature ist ungeeignet als deterministischer Build-Auslöser von Tags und Branches.

 

 

GIT-PLUGIN ODER ‘ES FUNKTIONIERT!’

Das Jenkins Git-Plugin ist das eigentlich Arbeitstier. Das GitHub-Plugin hat eigentlich keine ernstzunehmen Features, wobei das Git-Plugin wiederum die ganze Arbeit erledigt. Wenn man die Dokumentation des Git-Plugins genau ließt, so stößt man auf den Abschnitt Push notification from repository . Dieser offenbart einen anderen Weg der uns den GitHub Webhook nutzbar machen lässt.

Die URL die wir nun in unseren GitHub Webhook eintragen ist die folgende:

https://jenkins.foo/git/notifyCommit?url=https://github.com/codeclou/customfield-editor-plugin.git

GitHub Webhook für Git-Plugin Notify
‍GitHub Webhook für Git-Plugin Notify

Was wir direkt sehen ist, dass wir keine Authentifizierung benötigen, weshalb ich diesen Endpoint mit meinem vorgeschalteten NGINX geschützt habe. Nun müssen wir einen anderen Build Auslöser wählen:

Jenkins Git-Plugin Build Auslöser
‍Jenkins Git-Plugin Build Auslöser

Jeder der Das SCM Polling Feature von früher kennt und jetzt sagt ‘Nein! Das belastet GitHub wenn da ständig gepollt wird!’, der sollte die Dokumentation genau lesen. Wenn man nämlich das Zeitplanfeld leer lässt, so wird nur gepollt, wenn eine Push-Notification ausgelöst wird. Und das polling, was dann passiert, ist auch nicht besonders belastend für das den SCM Host (GitHub).

 

Wichtig ist nun noch einzustellen, dass alle Tags und alle Branches gebaut werden sollen. Das geschieht über folgende Refspec im Source-Code-Management:

github:45b1c21678440ca44bc8e3527f1f347d
Source Code Management - Alle Branches und alle Tags
‍Source Code Management - Alle Branches und alle Tags

 

Und siehe da, nun baut auch das richtige Tag.

Jenkins Build - Richtiger Tag
‍Jenkins Build - Richtiger Tag

 

 

AUTOMATISIERTER GITHUB RELEASE ASSET UPLOAD

Nachdem nun unsere Tags deterministisch gebaut werden, wollen wir folgenden Abschnitt in unser ‘jenkins.sh’ Build-Script einbauen.

github:cfa9f0d40fb04f4a059f1f676b57bfd1

Variablen, die vom Git-Plugin bereitgestellt werden sind bspw. ‘GIT_BRANCH’ und ‘GIT_COMMIT’. Die Variable ‘GITHUB_AUTH_TOKEN’ stellen wir als Umgebungsvariable global bereit und sie sollte einen Personal Access Tokenmit Schreibrechten auf das gewünschte Repository enthalten.

Wir überprüfen also ob in der ‘GIT_BRANCH’ Variable die Zeichenkette ‘tags’ vorkommt. Wenn ja, dann erstellen wir ein GitHub Release und laden die Artefakte hoch. Dazu bedienen wir uns der GitHub API und den Kommandozeilen Tools ‘curl’ und ‘jq’. Die Konvention die wir verwenden ist dabei, dass das Git Tag gleichnamig zum GitHub Release ist.

Das Ergebnis sieht dann so aus:

GitHub Release - Build Assets
‍GitHub Release - Build Assets

 

 

FAZIT

Auch mit Jenkins lassen sich Build Artefakte zu einem GitHub Release publishen. Mit dem ‘publish-github-release-assets-helper’ gestaltet sich das Publishen von Release Assets sehr einfach. Zu haben ist er auf GitHub:

https://github.com/codeclou/publish-github-release-assets-helper

Meiner Meinung nach hat man nun fast denselben Komfort erreicht wie bei Travis CI.

Wenn Sie noch mehr Kontrolle über Git in ihren Jenkins Jobs haben wollen, dann könnte folgendes Plugin evtl. interessant sein:

https://github.com/codeclou/jenkins-github-webhook-build-trigger-plugin

Ich habe es geschrieben, weil mich das ständige ‘git fetch’ bei einem Job Trigger sehr genervt hat und das Git Plugin trotz aller im Webhook verfügbaren Informationen dann doch den falschen Tag/Branch cloned.

Wir haben nicht nur Erfahrung mit Jenkins und Travis CI sondern auch mit Architektur & Entwicklung. Wenn Sie Unterstützung bei Ihren Projekten benötigen, schreiben Sie uns unverbindlich einfach über das nachfolgend angezeigte Kontaktformular an.