Im letzten Artikel dieser Blogserie haben wir einen neuen simplen Workflow angelegt. In diesem Artikel geht es nun um den eigentlichen Kern und Namensgeber: Actions. Was ist eine Action und was ist ein Step? Wenn ich Azure DevOps Pipeline schon kenne, wie finde ich mich hier zurecht? Dies wird im Folgenden anhand der Migration der Pipeline unseres Tools Voting Extension erklärt.
Wenn man einen von GitHub vorgeschlagenen Workflow anlegt, sind dort bereits ein paar Steps vordefiniert, welche Text auf der Konsole ausgeben (siehe Codebeispiel 1).
Wer bereits mit YAML-Pipelines in Azure DevOps gearbeitet hat, dem wird die Struktur bereits bekannt vorkommen.
Ein Workflow kann mehrere Jobs enthalten, welche nacheinander, parallel oder nur unter definierten Bedingungen ausgeführt werden können, z.B. ein Test-Job, der nur ausgeführt wird, wenn der vorherige Build-Job erfolgreich ist. Für jeden Job muss der Runner-Typ mit runs-on ausgewählt werden, womit auch das Betriebssystem definiert wird, auf welchem der Job ausgeführt wird. Im vorgeschlagenen Workflow ist standardmäßig ein Ubuntu-Runner ausgewählt. Bei der Migration eines .NET Framework Builds würde man hier z.B. windows-latest wählen, mehr Details dazu sind auch in der GitHub Doku zu finden.
Ein Job enthält mehrere Steps, welche innerhalb des Jobs sequenziell ausgeführt werden. Es gibt verschiedene Step-Typen, die im Folgenden näher betrachtet werden sollen.
Der Run-Step
Der einfachste Typ ist der Run-Step, welcher mit dem Schlüsselwort run definiert werden kann. Dieser führt auf der Konsole des Host-Systems Befehle aus. Welche Shell (PowerShell, Bash, etc.), Umgebungsvariablen oder welches Arbeitsverzeichnis verwendet werden soll, können konfiguriert werden. Ein Name für den Step, welcher im Log angezeigt wird, kann optional auch vergeben werden.
Die Migration von Azure DevOps Tasks mit Batch- oder PowerShell-Scripts ist damit denkbar einfach: Shell-Typ konfigurieren und das Inline-Script oder das Script-File aufrufen. Der vorgeschlagene Workflow enthält sogar bereits Beispiele für ein- und mehrzeilige Inline-Scripts.
In unserem Beispiel der Voting Extension legen wir für den Job Preview_Build drei Run-Steps an, um die npm-Abhängigkeiten zu installieren, unser Manifest-File zu aktualisieren und den Build auszulösen (siehe Codebeispiel 2). Alles funktioniert über bereits definierte npm-scripts, welche über Konsolenbefehle aufgerufen werden:
Für das Aktualisieren des Manifest-Files setzen wir mit der env Eigenschaft die Umgebungsvariablen, welche für den aktuellen Job gültig sind und mit der %-Notation in den Batch-Run-Steps referenziert werden können. Mehr zur Verwendung von Variablen erfahren Sie im nächsten Blog-Artikel.
Beim Script Error Handling gibt es ein paar Unterschiede und bei der Migration von Scripts sollte man ganz genau darauf achten, wann der Task bzw. die Action mit einem Error fehlschlagen soll.
Der Action-Step
Ein weiterer oben eingesetzter Step ist das Checkout des Repositorys. Es handelt sich hierbei nicht um einen Run-Step, sondern um eine Action. Dies ist ein weiterer Step-Typ. Es gilt: Jede Action ist ein Step, aber nicht jeder Step ist eine Action.
Das Schlüsselwort für Actions lautet uses. Eine Action ist eine wiederverwendbare und in der Regel parametrisierbare Funktion und damit vergleichbar mit einem Task in Azure Pipelines. Actions können z.B. aus dem Marketplace oder aus dem eigenen Repository genutzt werden (Details siehe Dokumentation).
Der Step Checkout ist eine von GitHub im Marketplace veröffentlichte Action und führt einen Checkout des Git-Repositorys durch. Mindestens muss das uses-Schlüsselwort angegeben werden. Ein Name und andere Parameter sind hier optional.
Bei der Migration einer bestehenden Azure DevOps Pipeline wird man häufig einen speziellen Task verwenden (z.B. Custom Tasks, die über eine Extension kommen), der nicht durch einen Konsolenaufruf ersetzt werden kann. Im GitHub Marketplace gibt es allerdings oft eine Action, welche man ersetzend für den Task nutzen kann.
Als Beispiel hierfür lässt sich der von uns verwendete Task Replace Tokens anführen, welchen wir bei der Voting Extension nutzen, um z.B. den Instrumentation Key für Application Insights in einer JS-Datei zu ersetzen. Eine kurze Suche nach replace im GitHub Marketplace ist erfolgreich (siehe Abbildung 1).
Nach Auswahl der Action erscheint direkt eine kleine Dokumentation mit Beispiel-Code dazu. Meist ist dies für die übliche Verwendung ausreichend. Die Detailseite im Marketplace ist zusätzlich noch verlinkt. Der angepasste Beispielcode sieht dann bei uns so aus (siehe Codebeispiel 3).
Die Parameter einer Action werden unter der Eigenschaft with angegeben. Es gibt optionale und zwingend notwendige Parameter. In diesem Fall ist der Parameter files Pflicht, die tokenPrefix und tokenSuffix sind optional. Achtung: Die kurze Doku beschreibt files als optional, die Marketplace-Seite allerdings nicht; hier gibt es immer mal wieder Abweichungen. Die zu ersetzenden Token sind als Umgebungsvariable anzugeben.
Custom Actions
Sollte man im Marketplace nicht fündig werden, kann man auch eigene Actions implementieren. Eine eigene Custom Action kann man im Marketplace veröffentlichen oder im eigenen Repository belassen und von dort referenzieren.
Es gibt zwei Typen von Actions: JavaScript und Docker Container. Wer also seine Action nicht in JavaScript bzw. TypeScript schreiben möchte, kann seiner Kreativität in einem Docker Container freien Lauf lassen, da es hier keine Festlegung auf eine Programmiersprache gibt. Damit könnte man also einen aufwändigen Azure DevOps Task, für den es keine entsprechende GitHub Action gibt, in einem Docker Container kapseln und auch in GitHub als Action nutzen, ohne ihn in JavaScript nachimplementieren zu müssen. Docker Container müssen in einer Public Registry verfügbar sein.
Fazit
Die Migration von Tasks aus Azure DevOps nach GitHub Actions fällt nicht schwer. Für viele Tasks gibt es eine entsprechende Action im GitHub Marketplace. Im Gegensatz zu Azure DevOps bietet GitHub zwar keine grafische Oberfläche für das Editieren des Workflows, jedoch ist die Benutzung des Web-Editors mit der direkt verfügbaren Dokumentation und Autovervollständigung sehr hilfreich. Wer bereits mit YAML-Pipelines in Azure DevOps gearbeitet hat, wird sich schnell zurechtfinden. Es gibt durchaus Unterschiede (z.B. beim Umgang mit Scripts), die man bei einer Migration beachten muss.
In den Actions können Variablen genutzt werden, um z.B. zwischen den Actions Informationen auszutauschen. Der Umgang mit Variablen und Secrets wird im nächsten Blogartikel behandelt.
Sprechen Sie uns an, wenn Sie Fragen haben oder Unterstützung in Ihrem Softwareentwicklungsprozess benötigen: Von der ersten Idee über die Entwicklung mit einer Build- und Release-Pipeline bis hin zur Inbetriebnahme und Wartung. Wir führen Sie gerne ans Ziel.