DevOps mit GitHub - Teil 2: Packages bauen und veröffentlichen mit GitHub Actions

Wie man GitHub Actions als Build-Pipeline nutzt, um bei jedem Commit automatisch Gradle-Artefakte zu bauen und in GitHub Packages zu veröffentlichen.

  • Alexander Praschek Alexander Praschek
  • date icon

    12. Sep. 2020

DevOps mit GitHub - Teil 2: Packages bauen und veröffentlichen mit GitHub Actions

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.

Was ist GitHub Actions?

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.

Wie funktioniert es?

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.

Wie kann ich es in mein Gradle-Projekt einbauen?

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

Die Action erstellen

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.

Unser Projekt anpassen

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:

  1. Wir erhöhen die Version auf 1.0.1, um beim Publishen einen Versionskonflikt zu vermeiden. Diese Änderung muss in beiden Modulen und im Root-Projekt vorgenommen werden.
  2. Wir ersetzen die URL des Zielrepositories, damit es in unserem neuen Repository landet. Diese Änderung muss in beiden Modulen vorgenommen werden.
  3. Wir erhöhen die Version der Library-Dependency ebenfalls auf 1.0.1, um das neue Artefakt zu verwenden. Diese Änderung ist nur im main-Modul notwendig.

Authentifizierung bei GitHub Packages

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.

In ein anderes GitHub Packages Repository publishen

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.

Namenskonflikte verhindern

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.

Die Action ausführen

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.

Fazit

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.

Also published in English at medium.com.

Fand den Artikel interessant?

Abonniere unseren Newsletter und erhalte neue Beiträge direkt ins Postfach.

Insights

Aktuelle Beiträge

Die neuesten Artikel aus unserem Blog: technische Deep Dives, Erfahrungsberichte und Einblicke in unsere Arbeit.

Leveling up! Wie du die Herausforderung verteilter Transaktionen in Zeebe lösen kannst
date icon

01. Dez. 2025 · Marco Schäck

Leveling up! Wie du die Herausforderung verteilter Transaktionen in Zeebe lösen kannst

Ein umfassender Guide zu verteilten Transaktionen in Zeebe: Von Phantom-Instanzen über das Outbox Pattern bis hin zu Idempotenz und SAGA.

Weiterlesen
Komplexität navigieren: Von Verwirrung zu Klarheit durch klare Perspektiven
date icon

24. Okt. 2025 · Marco Schäck

Komplexität navigieren: Von Verwirrung zu Klarheit durch klare Perspektiven

Zwei Perspektiven zur Kategorisierung von Komplexität in Softwaresystemen: Wo lebt sie (lokal vs. global) und warum existiert sie (essenziell vs. akzidentell)?

Weiterlesen
Komplexität meistern – Wie Prozessautomatisierung gelingt
date icon

12. Mai 2025 · Dominik Horn

Komplexität meistern – Wie Prozessautomatisierung gelingt

Erfahrungen aus einem Jahrzehnt Prozessautomatisierung: Warum Kontext, Teamstrukturen und organisatorische Reife wichtiger sind als Technologie allein.

Weiterlesen

Innerhalb eines Tages weißt du, wo du stehst.

Kein Verkaufsgespräch, sondern eine ehrliche Einschätzung, ob und wie Automatisierung dir hilft. Kostenfrei.

Termin buchen

Kein Commitment. Kein Pitch-Deck. Nur Klarheit.