Da wir tagtäglich mit Open Source Tools und Anwendungen arbeiten, die meist von anderen Menschen kostenfrei bereitgestellt werden, wollen wir auch gern unsere selbst geschriebene Software für andere bereitstellen. Daher haben wir beschlossen, unsere Open Source-Software über GitHub bereitzustellen.

In diesem Beitrag möchte ich Euch gerne vorstellen, wie wir GitHub einsetzen, um unsere Open Source Arbeitsweise zu unterstützen. Für ein besseres Verständnis starten wir aber zuerst mit einer kurzen Abgrenzung der einzelnen Begrifflichkeiten.

Was ist eigentlich dieses Git und was hat GitHub damit zu tun?

Einfach ausgedrückt ist Git ein Versionskontrollsystem, mit dem man seinen Quellcodeverlauf verwalten und verfolgen kann. GitHub wiederum ist ein Cloud-basierter Hosting-Service, mit dem man seine Git-Repositories verwalten kann. Dabei ist GitHub darauf ausgelegt, Open-Source-Projekte, die Git nutzen, bei der Verwaltung zu unterstützen.

Welche Möglichkeiten habe ich bei der Arbeit mit GitHub?

GitHub Actions ist eine Plattform für kontinuierliche Integration und kontinuierliche Bereitstellung (CI/CD), mit derer man seine Build-, Test- und Bereitstellungspipeline automatisieren kann. GitHub Actions sind einzelne Aufgaben, die man kombinieren kann, um Jobs zu erstellen und den Workflow anzupassen.

Und was sind dann nun GitHub Workflows?

Man unterscheidet bei GitHub zwischen Workflows und reusable Workflows: 

Ein GitHub Workflow ist ein konfigurierbarer automatisierter Prozess, der einen oder mehrere Jobs ausführen kann. Die Workflows werden durch eine im Code hinterlegten YAML-Datei definiert, die einzelnen Workflows werden typischerweise unter dem Verzeichnis .github/workflows abgelegt.

Durch unterschiedlich definierte Ereignisse werden diese Workflows ausgeführt. Diese Ereignisse sind zum Beispiel:

  • ein Ereignis im Repository, z.B. push in den main Branch
  • der manuelle Aufruf des Workflows
  • definiert durch einen Zeitplan

Reusable oder wiederverwendbare Workflows sind sogenannte „called“ Workflows. Das heißt, der Workflow wird an einer zentralen Stelle definiert und durch einen „call“ an anderer Stelle genutzt. Ein reusable Workflow kann dabei mehrere Workflows gleichzeitig aufrufen.

Okay, und wie läuft das jetzt alles zusammen?

Zusammengefasst kann man sagen: GitHub Actions enthalten Code, der gegen das Repository ausgeführt werden soll. Welche Actions mit welcher Konfiguration genutzt werden sollen, wird über die Jobs im Workflow definiert. Unter der Verwendung von reusable Workflows kann man dies an zentraler Stelle definieren und mehrfach nutzen.

Unsere GitHub Organisation

In unserer GitHub Organisation nutzen wir aktuell reusable Workflows hauptsächlich, um Workflows zu definieren, die wir dann in unseren diversen Repositories nutzen.

Die Vorteile hierbei für uns sind:

  • Wir definieren die einzelnen Jobs des Workflows nur einmal
  • Notwendige Anpassungen wie eine Aktualisierung der GitHub Actions müssen wir nur einmal statt an allen Repositories, die den Workflow nutzen, durchführen
  • Wir können in allen Repositories auf die gleiche Konfiguration für unsere Workflows zurückgreifen, z.B. Linting Regeln, Releases oder Builds
  • Die Menge an Code, der geschrieben und verwaltet werden muss, kann stark reduziert werden

Wie greifen die einzelnen GitHub Optionen nun in unserer Organisation ineinander?

Für ein besseres Verständnis beschreiben wir das Vorgehen anhand von Bespielen mit unseren Terraform-Modulen.

Aktuell haben wir mehr als 25 Repositories. Dort enthalten sind Terraform Module zum Verwalten von Ressourcen in der Azure. Um einen möglichst gleichen Grundaufbau und Definition der Tests für diese Module zu haben, haben wir beschlossen alle oben genannten Werkzeuge zu nutzen. 

Wie sieht die Umsetzung jetzt konkret aus?

Ich betrachte die Umsetzung aus zwei Perspektiven: aus der Organisationssicht sowie aus der Repository-Sicht.

Aus Sicht der Organisation möchten wir bestimmte Jobs, Settings und andere Dinge global definieren und zur Wiederverwendung bereitstellen.

Hierfür haben wir ein Repository zur zentralen Definition erstellt, welches auf GitHub zu finden ist. Hier werden auch unsere erstellten reusable Workflows hinterlegt. 

Um einen Workflow reusable zu machen, müssen die Values für on den Wert  workflow_call  beinhalten.

Zur Definition der Jobs innerhalb der reusable Workflows greifen wir sowohl auf GitHub Actions zu, die über den Marketplace bereitgestellt werden, als auch unsere selbst erstellten GitHub Actions.

Aus Sicht des Repositories möchten wir Konfigurationen, Tests, Workflows etc. soweit möglich vordefiniert nachnutzen, damit man sich inhaltlich nur um seinen speziellen Anwendungsfall, hier den Terraform-Code für Azure-Ressourcen, konzentrieren kann.

Die Grundstruktur unserer Module haben wir über ein Repository Template definiert. Daraus erstellen wir die einzelnen Repositories für die Module, z.B. terraform-azurerm-container.

Im Template sind bereits die Workflows definiert, die innerhalb des Repositories genutzt werden sollen. Dabei greifen wir auf die bereits erstellten reusable Workflows aus dem .github  Repository zurück. 

Wie bereits erwähnt wollten wir aber auch für unsere Module Tests durchführen und dies über einen Test Workflow in allen Repositories integrieren. Nach etwas Recherche haben wir uns entschieden dies mittels Gruntwork Terratest durchzuführen. 

Entsprechend unserer Anforderungen haben wir daher eine eigene GitHub Action erstellt. In dieser Action ist ein entsprechender GoLang Code hinterlegt, der unsere Testanforderungen mittels Terratest abdeckt. Dabei haben wir auch hier darauf geachtet, die Action so generisch wie möglich zu halten, sodass bei der Nutzung der Action nur über eine definierte Konfigurationsdatei tests/terratest.yaml, die für das entsprechende Modul spezifische Testkonfiguration an die Action übergeben wird.

Zusammengefasst können wir festhalten, dass wir mithilfe von workflows, reusable workflows und actions für unsere Terraform Modul Repositories einfach und schnell eine Release-, Linting- und Testpipeline bereitstellen und nutzen können:

  • Linting des Terraform-Codes
  • Automatisierte Releases, Changelog und Tags
  • automatisierte Erstellung der Dokumentation des Codes (Terraform Docs)
  • Tests mit Hilfe von terrascan
  • Prüfung des Codes auf Vulnerabilities
  • Unit und Integrationstests mit terratest

Darüber hinaus nutzen wir dieses Vorgehen auch bei unseren anderen Repositories, z.B. zum Upload von Ansible-Collections in die Ansible Galaxy.

Aktuell beschäftige ich mich mit der Automatisierung unser GitHub Repository Settings, mittels GitHub Apps. Ein entsprechender Artikel hierzu folgt.

Kolleg*innen gesucht:

Hier geht’s zu den aktuellen Stellenausschreibungen: