Blog

Wie setzen wir die Gitlab-CI ein?

26.11.2020 // Gregor Goldbach

In meinem Artikel über die Optimierung von Docker-Images habe ich erwähnt, dass wir die »Gitlab-CI« einsetzen. In diesem Artikel beschreibe ich nun näher, was das eigentlich ist und welche Erfahrungen wir gemacht haben.

Was bedeutet CI?

Mit »CI« wird in der Software-Entwicklung »continuous integration« bezeichnet, also die fortlaufende Integration von Software-Komponenten. Dies ist ein Vorgehen im Team und weniger ein Werkzeug, bei dem Änderungen an der gemeinsamen Code-Basis fortlaufend an einer definierten Stelle zusammengeführt und auf ihre Qualität hin untersucht werden.

Diese Untersuchung besteht in der Regel aus einer Reihe von automatisierten Tests, die Abweichungen von gewünschten Eigenschaften aufzeigen sollen. Hierzu kann auch das Einhalten von Codier-Richtlinien zählen.

Durch die häufige Integration und einem hohen Grad an Automatisierung möchte das Team sicherstellen, dass Fehler und Abweichungen schneller gefunden und behoben werden können.

Die fortlaufende Integration ist also ein Baustein, um qualitätssichernde Maßnahmen im Softwareentwicklungsprozess umzusetzen.

Gitlabs CI-Umsetzung

Das Produkt Gitlab unterstützt fortlaufende Integration durch eine textuelle Beschreibung von »Pipelines«, in denen konfigurierbare Befehle ausgeführt werden.

Nach einem Push von Änderungen in einem Repository wird ein Docker-Container gestartet, in dem dann die beschriebenen Befehle ausgeführt werden.

Das folgende Beispiel zeigt eine hypothetische Distribution Foo::Bar::Baz, die mit Dist::Zilla in Ubuntu gebaut und getestet wird.

image: ubuntu

stages:
  - build

build:
  stage: build
  script:
    - dzil build
    - dzil cover
    - dzil test
  coverage: '/^Total.+\s+(\d+.\d)$/'
  artifacts:
    when: always
    name: "${CI_BUILD_STAGE}_${CI_BUILD_REF_NAME}"
    paths:
      - foo-bar-baz-*.tar.gz

Diese Befehle werden typischerweise das Compilieren und Linken von Software sein, an die sich Testautomatisierung und weitere Prüfungen anschließen.

Wenn alle Befehle erfolgreich ausgeführt wurden, ist der Build erfolgreich. Erfolg oder Misserfolg eines Builds werden dem Entwickler, dessen Änderungen die Pipeline ausgelöst haben, per E-Mail mitgeteilt. Der Zustand eines Builds ist zusätzlich im Gitlab-Projekt sichtbar.

Welche Arten von Pipelines es gibt und wie dies in Gitlabs Oberfläche dargestellt wird, ist in Gitlabs Dokumentation nachzulesen.

Wie nutzen wir die Gitlab-CI?

Eine Pipeline wird wie oben beschrieben nach einem Push der Änderungen gestartet. Bei der Konfiguration dieser Pipelines legen wir auf zwei Aspekte großen Wert: Geschwindigkeit und Reproduzierbarkeit des Builds.

Geschwindigkeit ist für uns wichtig, da wir binnen weniger Minuten Rückmeldung über die Qualität der Änderungen erhalten wollen. Wenn hier etwas bricht, wollen wir den Fehler sofort korrigieren, da diese Behebungen meist einfacher sind als bei großen Änderungen.

Geschwindigkeit erreichen wir durch konfektionierte Docker-Images. Außerdem stimmen wir die Reihenfolge der Tests aufeinander ab und verfolgen beim Schreiben der Tests einen »fail fast«-Ansatz. Wenn ein Build fehlschlägt, bekommen wir so früh Rückmeldung.

Die Reproduzierbarkeit eines Builds ist für uns wichtig, damit wir Builds nachvollziehen können, indem wir die Docker-Images auf beliebigen Systemen bauen. In der Vergangenheit hatte uns Gitlab öfter Fehler in Builds gemeldet, die wir dann lokal auf unseren Entwicklungsrechnern nicht nachvollziehen konnten. Grund hierfür war die Installation von Abhängigkeiten und dadurch entstandene Versionsunterschiede.

Die Reproduzierbarkeit erhalten wir, indem wir so gut es geht die Versionen der Abhängigkeiten angeben und während des Builds keine Komponenten nachinstallieren. Da Installationen entfallen, erhöht sich als Nebenwirkung auch die Build-Geschwindigkeit.

Dist::Zilla

Für uns hat sich Dist::Zilla als sehr hilfreich erwiesen. Einerseits ermöglichen uns die Kommandos dieses Werkzeugs, die Konfiguration einer Pipeline übersichtlich zu halten. Andererseits bietet die Funktionalität von dzil vieles, was wir sinnvoll einsetzen können.

Kommandos, die wir nutzen, sind zum Beispiel »test« für das Ausführen der Tests, »build« zum Erstellen der Distribution und »cover« zum Messen der Testabdeckung.

Wir setzen Dist::Zilla ein, um am Ende eines Builds die Distribution als Artefakt »an den Build zu hängen«. Das von dzil erstellte Archiv wird einem Build zugeordnet; wir können es dann im Browser, in anderen Projekten oder über die API übertragen.

Auch bei der Versionsverwaltung ist Dist::Zilla nützlich: Sein git-Bundle hilft dabei, Branches nach dem Veröffentlichen einer Distribution zu taggen. Somit ist automatisiert und nachvollziehbar im Git-Repository eine Versionshistorie abrufbar.

Zusammenfassung

Das Produkt Gitlab hilft einem Team beim fortlaufenden Integrieren von Software-Komponenten. Entwickler können »Pipelines« über Textdateien beschreiben, in denen Befehle nach Änderungen einer gemeinsamen Code-Basis ausgeführt werden. Wir können damit schnelle Rückmeldungen über Code-Änderungen und reproduzierbare Builds erhalten. Dist::Zilla hilft uns, einen Build übersichtlich zu beschreiben und effizient durchzuführen.

Weiterlesen


Permalink: