Also published in English at medium.com.
Im zweiten Teil dieser Serie werden wir uns damit beschäftigen, wie wir GitHub Actions als Build-Pipeline nutzen können. Bei jedem Commit wird aus unserem Gradle-Projekt ein Artefakt gebaut, das anschließend automatisch in GitHub Packages veröffentlicht wird.
Zeitgleich mit der Ankündigung für GitHub Packages wurde auch GitHub Actions angekündigt. Damit wird es möglich, auf Events mit unterschiedlichen Aktionen zu reagieren. Dabei werden zahlreiche unterschiedliche Events unterstützt.
Mit GitHub Packages haben wir uns bereits im ersten Teil dieser Serie beschäftigt. Den entsprechenden Post findet ihr hier. Dieser Teil baut auf dem Projekt auf, das wir im ersten Blogbeitrag erstellt haben.
Im Grunde lässt sich GitHub Actions als eine Pipeline beschreiben, die bestimmte Aktionen als Reaktion auf die bereits erwähnten Events ausführt. Während herkömmliche Pipelines wie bspw. Jenkins normalerweise nur auf neue Commits reagieren und daraufhin einen Build ausführen, ist GitHub Actions breiter aufgestellt.
Auch wenn die vermutlich am häufigsten genutzten Events tatsächlich das Pushen neuer Commits und das Erstellen neuer Pull Requests sind, können damit auch Aktionen angelegt werden, die bspw. beim Anlegen eines neuen Issues ausgeführt werden. Alle verfügbaren Events sind hier aufgelistet.
Der Service ist für öffentliche Repositories kostenfrei, private Repositories erhalten 2000 Build-Minuten pro Monat umsonst. Kostenpflichtige Tarife haben höhere Inklusivminuten. Zusätzliche Minuten können kostenpflichtig hinzugebucht werden mehr. Aktionen werden normalerweise in Linux-Containern ausgeführt. Aktionen in Windows- oder macOS-Containern werden mit Faktor 2 bzw. 10 abgerechnet.
Eine GitHub Action besteht aus einer YAML-Datei, die im Projekt-Repository abgelegt wird. Darin wird definiert, welche Schritte ausgeführt werden. GitHub prüft für jedes Event, ob eine passende Action definiert ist, und führt diese aus.
Neben einfachen Bash-Befehlen können auch Actions aus dem Marketplace verwendet werden, die häufig benötigte Aktionen ausführen wie das Auschecken von Quellcode oder das Bereitstellen einer bestimmten Java-Version.
Eigene Actions können per NodeJS definiert werden und in eigenen Repositories wiederverwendet werden. Alternativ können diese im Marketplace veröffentlicht und somit allen Anwendern zugänglich gemacht werden.
Wir bauen auf dem Projekt auf, das wir im letzten Teil der Serie bereits angelegt haben. Den Code dafür findet ihr hier. Alternativ könnt ihr der Schritt-für-Schritt-Anleitung aus dem letzten Teil folgen.
Im letzten Post haben wir bereits ausprobiert, wie man die gebauten Artefakte manuell in GitHub Packages veröffentlichen kann. Nun werden wir das mit GitHub Actions kombinieren und bei jedem Commit automatisch ausführen.
Sämtlicher Code, den wir in den folgenden Abschnitten erstellen, ist auch in diesem Repository zu finden: https://github.com/Miragon/devops-github-actions
Dafür legen wir zunächst den Ordner .github/workflows
im Root-Verzeichnis unseres Projekts an. Darin erstellen wir die Datei publish.yaml
. Diese definiert die Action und sieht wie folgt aus:
name: Build & Publish on: # Defines the events that this action responds to push: # Run whenever new commits are pushed branches: [ master ] # Only if target branch is master jobs: build: runs-on: ubuntu-latest # The container to run this action on steps: - name: Checkout sources uses: actions/checkout@v2 # Use action from marketplace - uses: actions/setup-java@v1 with: # Pass parameters to action java-version: '11.0.4' java-package: jdk architecture: x64 - name: Build and publish JAR # Used to execute gradle commands run: gradle \ -Pgpr.key=${{ secrets.GITHUB_TOKEN }} \ -Pgpr.user=$GITHUB_ACTOR \ :devops-github-packages-library:build \ :devops-github-packages-library:publish
Innerhalb der Action wird zunächst der Code ausgecheckt. Anschließend wird Java 11 bereitgestellt, ein Gradle-Build ausgeführt und das Ergebnis veröffentlicht.
Im Repository können wir außerdem die Dateien gradle.properties
in den beiden Modulen entfernen. Zudem müssen wir die build.gradle
-Dateien anpassen:
Um erfolgreich pushen zu können, brauchen wir normalerweise einen entsprechenden Token, der uns den Zugriff erlaubt. Falls wir direkt im selben Repository veröffentlichen, benötigen wir diesen Token nicht.
Stattdessen können wir die von GitHub automatisch bereitgestellte Variable $GITHUB_ACTOR
und das Secret GITHUB_TOKEN
verwenden. Der GitHub Actor ist der Name des Accounts, welcher die Action ausgelöst hat. Der GitHub Token enthält einen temporären Token, welcher Berechtigungen für das aktuelle Repository enthält.
Falls es unser Ziel ist, in einem anderen Repository zu veröffentlichen, müssen wir die Properties gpr.user
und gpr.token
überschreiben und dafür den letzten Schritt in der publish.yaml
anpassen.
# ... - name: Build and publish JAR # Used to execute gradle commands run: gradle \ -Pgpr.key=${{ secrets.GPR_KEY }} \ -Pgpr.user=${{ secrets.GPR_USER }} \ :devops-github-packages-library:build \ :devops-github-packages-library:publish
Anschließend müssen wir in den Repository-Einstellungen zwei neue Secrets anlegen (GPR_USER
und GPR_TOKEN
) und darin die Zugangsdaten speichern, die wir bisher in der gradle.properties
-Datei hatten.
Die Secrets schützen zwar die Credentials vor einem unerlaubten Kopieren, allerdings kann jeder mit Push-Zugriff auf das Repository sie im Rahmen einer Action verwenden.
Da wir in ein anderes Repository als im letzten Teil der Serie publishen wollen, müssen wir den Package-Namen ändern. Andernfalls liefert GitHub einen Fehler 422 Unprocessable Entity
zurück. Das liegt daran, dass Package-Gruppe und -Name innerhalb einer Organisation / eines Accounts eindeutig sein müssen.
Aus diesem Grund fügen wir folgende Zeile in der build.gradle
des library-Moduls ein:
// Configures the publishing publishing { publications { gpr(MavenPublication) { artifactId 'devops-github-actions-library' // <-- Add this line from(components.java) // ... } } }
Außerdem müssen wir die Dependency im main-Modul ebenfalls umbenennen in devops-github-actions-library
.
Sobald wir unsere Änderungen committen und nach GitHub pushen, wird die neue Action automatisch gestartet. Um dies zu prüfen, öffnen wir GitHub, wo wir neben unserer letzten Commit-Message einen kleinen gelben Punkt sehen. Dieser gibt an, dass die Action gerade läuft. Das Ergebnis wird nach Abschluss des Builds als grüner Haken oder rotes Kreuz dargestellt.
Um die Build-Details zu sehen, klicken wir in unserem Repository auf Actions, wählen unseren Commit aus und klicken links auf Build & Publish / build
. Dort werden die Logs unserer Action live gestreamt, während sie läuft. Sobald der Build abgeschlossen ist, können wir wieder auf die Startseite unseres Repositories wechseln, um dort die neu erstellte Version zu betrachten.
In diesem Teil der Serie haben wir das Bauen und Veröffentlichen eines Gradle-Projekts mithilfe von GitHub Actions betrachtet. Im nächsten Teil werden wir das Bauen eines Docker Images in GitHub Actions ausprobieren.
Rechtliches