In diesem Artikel gebe ich einen Überblick über die Toolchain für Continuous Integration und Continuous Delivery unserer iOS-Projekte, die wir täglich verwenden. Außerdem werde ich auf einige Erkenntnisse eingehen, die wir in den letzten Jahren gewonnen haben. Niemand wird bezweifeln, dass CI/CD heutzutage eine wichtige Rolle in der Softwareentwicklung spielt. Eine App kann jedes Mal automatisch getestet werden, wenn es einen Commit gibt oder zwei Branches zusammengeführt werden sollen. Es ist auf diesem Weg genauso einfach, eine neue Version für Alpha- und Beta-Tester bereitzustellen oder im App Store zu veröffentlichen. Es gibt viele Tools und Plattformen, die dabei helfen, eine CI/CD-Pipeline aufzubauen. Alles, was ich hier vorstelle, ist also nur eine mögliche Lösung. Jeder muss selbst entscheiden, ob es den eigenen Bedürfnissen entspricht oder nicht.
Das Setup
Wir verwenden git als Versionierungssystem und Bitbucket als Host für unsere Repositories. In Bitbucket erstellen wir Branches und Pull-Requests, wenn ein Branch bereit dafür ist, zusammengeführt zu werden. Um den gesamten CI-Prozess zu orchestrieren, verwenden wir Jenkins. Jenkins ist ein Open Source Automatisierungs-Server. Er überprüft regelmäßig unsere Repositories auf neue Commits und Pull-Requests. Wenn er einen findet, startet er einen neuen automatisierten Testlauf. Diese Testläufe werden in der Jenkins-Welt als Job bezeichnet. In unserem Fall besteht ein Job hauptsächlich aus Unit-Tests und vielleicht einem Upload zu HockeyApp für Alpha-Tests. Dazu verwaltet Jenkins einen oder mehrere Knoten, die die eigentliche Arbeit erledigen. Ein Knoten ist im Grunde genommen ein anderer Computer, der in der Lage ist, den angeforderten Job auszuführen. In unserem Fall sind diese Knoten zwei Mac Minis.
Mindestens genauso hilfreich – wenn auch an einer anderen Stelle – ist Fastlane, wenn es um automatisiertes Testen geht. Es führt Unit- und UI-Tests mit unterschiedlichen Konfigurationen durch und kann auch den Upload zu HockeyApp oder TestFlight/iTunesConnect durchführen. Fastlane hat auch ein Tool, mit dem sich relativ einfach Zertifikate und Provisioning Profiles erstellen und aktualisieren lassen. Im Gegensatz zu Jenkins, der Jobs auf verschiedenen Knoten koordiniert, läuft Fastlane dann auf einem Knoten als Teil des Jobs.
Die Power von git
Werfen wir mal einen genaueren Blick auf git und wie wir es verwenden können, um damit die richtigen Jobs zur richtigen Zeit auszulösen – nicht mehr oder weniger. Wir verwenden git flow – oder zumindest eine abgespeckte Version davon – um zu strukturieren, wie unser Branching-Modell funktionieren soll. Jedes Mal wenn wir denken, dass der Teil an dem wir gerade gearbeitet haben fertig ist und in den Development- oder einen entsprechenden Feature-Branch zusammengeführt werden kann, erstellen wir einen Pull-Request und weisen ihn einem unserer Teamkollegen zu. Bei uns gilt die Regel, dass jeder Pull-Request von mindestens einem anderen Entwickler überprüft werden muss. Dieses Prinzip wird auch Peer Review genannt. Ebenso setzen wir voraus, dass alle automatisierten Tests erfolgreich durchgeführt wurden und dass es keine Merge-Konflikte gibt. Durch diese Bedingungen kann es etwas länger dauern, als das direkte Mergen in den Ziel-Branch – aber es lohnt sich!
Das Peer Review hat mehrere Vorteile:
- Es reduziert das Risiko, dass sich Fehler in den Code einschleichen
- Es hilft, die anderen Entwickler auf dem Laufenden zu halten
- Wir erhalten somit konstruktives Feedback zu unserem eigenen Code
Während ein Kollege meinen Pull-Request (PR) überprüft, hat Jenkins diesen neuen PR bereits bemerkt und mit dem Testen begonnen. Wenn ein Pull-Request getestet und erfolgreich überprüft wurde, wird er in unseren Development-Branch integriert. An dieser Stelle plant Jenkins gleich den nächsten Job, der den neuen Zustand auf Development testet, um sicherzugehen, dass beim Mergen nichts kaputt gegangen ist.
To be continued…