Zurück zur WebseiteInsights

DevOps mit GitHub - Teil 1: GitHub Packages mit Gradle

By Alexander Praschek
Published in DevOps
May 29, 2020
4 min read
DevOps mit GitHub - Teil 1: GitHub Packages mit Gradle

Also published in English at medium.com.

Vor ziemlich genau einem Jahr kündigte GitHub die Beta für ihr neuestes Produkt an – die GitHub Package Registry. Sie sollte das zentrale Repository für Artefakte werden, die aus dem Code entstehen, der bei GitHub gehostet wird. Neben npm sollten Docker, Maven, NuGet und RubyGems unterstützt werden.

Sie ist ein weiterer Baustein in GitHubs Strategie, den gesamten Weg von der Erstellung des Codes bis zur Auslieferung zu begleiten. Gleichzeitig wurde GitHub Actions angekündigt, mit denen wir uns im nächsten Teil der Serie beschäftigen werden.

Mittlerweile wurde das Produkt in GitHub Packages umbenannt und die Beta-Phase beendet. In diesem Blogbeitrag werden wir einen ersten Blick darauf werfen, wie GitHub Packages in Verbindung mit Gradle funktioniert.

Was ist GitHub Packages?

Während die meisten Artefakte auf MavenCentral zu finden sind, haben viele große Unternehmen zusätzlich interne Package Registries aufgebaut, in denen ihre internen Bibliotheken liegen.

GitHub Packages bietet genau das an, indem jedem GitHub-Account eine Registry bereitgestellt wird und jedes Repository gleichzeitig auch als Registry für Artefakte dienen kann.

Der Service ist für öffentliche Repositories kostenfrei, private Repositories erhalten 500MB Speicher und 1GB Traffic pro Monat umsonst. Kostenpflichtige Tarife haben höhere Inklusivvolumina. Zusätzlicher Speicher und Traffic kann kostenpflichtig dazugebucht werden mehr.

Wie kann ich es in mein Gradle-Projekt einbauen?

In den nächsten Abschnitten werden wir Schritt für Schritt ein neues Gradle-Multi-Module-Projekt anlegen und GItHub Packages integrieren. Wir verwenden dafür IntelliJ, aber eclipse sollte ähnliche Funktionalität bereitstellen.

Sämtlicher Code, den wir in den folgenden Abschnitten erstellen, ist auch in diesem Repository zu finden: https://github.com/Miragon/devops-github-packages

project
Unsere Package-Struktur in IntelliJ

Dafür legen wir zunächst ein neues Projekt „devops-github-packages“ mit zwei Modulen an: „devops-github-packages-main“ und „devops-github-packages-library“. Das main-Modul wird später eine Abhängigkeit auf das library-Modul haben, welches direkt aus GitHub Packages geladen wird.

Anschließend müssen wir die build.gradle im library-Modul anpassen. Dort aktivieren wir das Plugin „maven-publish“ und konfigurieren das Ziel-Repository:

plugins {
    id 'java-library'
    // Erlaubt das Publishen der Artefakte im Rahmen des Builds
    id 'maven-publish'
}

sourceCompatibility = JavaVersion.VERSION_11

group 'io.flowsquad.blog'
version '1.0.0'

repositories {
    mavenCentral()
}

// Konfiguriert das Publishen
publishing {
    repositories {
        // Das Ziel-Repository
        maven {
            // Der Name kann beliebig gewählt werden
            name = "GitHubPackages"
            // Die URL des Repositories, in dem die Artefakte veröffentlicht werden sollen
            url = "https://maven.pkg.github.com/FlowSquad/devops-github-packages"
            credentials {
                // Die Zugangsdaten (weiter unten beschrieben)
                username = project.findProperty("gpr.user")
                password = project.findProperty("gpr.key")
            }
        }
    }
    publications {
        gpr(MavenPublication) {
            from(components.java)
        }
    }
}

Die Zugangsdaten, die hier angegeben werden, müssen wir für dieses Modul in einer gradle.properties-Datei konfigurieren. Als Username verwenden wir dabei den GitHub-Login und als Key unseren Personal Access Token konfiguriert werden. Diesen legen wir im nächsten Schritt an.

gpr.user=githubUser
gpr.key=XXX

Um einen Personal Access Token anzulegen, müssen wir zunächst in den Profileinstellungen in GitHub links unten auf „Developer settings“ klicken. Dort wählen wir „Personal access tokens“ und dann „Generate new token“. Als Namen wählen wir „GitHub Packages Access Token“. Dieser benötigt folgende Scopes: repo, write:packages, read:packages und read:org (falls das Ziel-Repository innerhalb einer Organisation liegt).

Anschließend klicken wir auf „Generate token“ und kopieren den angezeigten Token in die oben erstellte gradle.properties-Datei. Der Token darf natürlich niemals eingecheckt werden, da er wie ein Passwort funktioniert.

Im library-Modul legen wir nun eine neue Klasse „LibraryClass“ an, die den Code enthält, den wir später aus dem main-Modul heraus aufrufen werden:

package io.flowsquad.blog.devops.github.packages.library;

public class LibraryClass {
    public String utilityMethod() {
        return "Hi, I'm a very expensive library method and do a lot of heavy calculations!";
    }
}

Wenn wir jetzt das Kommando „./gradlew :devops-github-packages-library:publish“ ausführen, baut Gradle unsere Bibliothek und veröffentlicht sie auf GitHub. Wir sollten sie dann im Reiter „Packages“ unseres Repositories sehen können:

github header
Der Packages-Tab in unserem GitHub-Repository

github
Wenn wir auf unsere Artefakt-Version klicken, sehen wir jede Menge Details dazu

Nun kümmern wir uns um das main-Modul. Auch hier muss die build.gradle angepasst werden. Der Dependencies-Block enthält das Library-Modul, das wir vorhin gebaut haben. Wir könnten natürlich auch direkt das Modul verlinken, aber wir wollen ja GitHub Packages testen, nicht wahr? ;)

plugins {
    id 'java'
}

sourceCompatibility = JavaVersion.VERSION_11

group 'io.flowsquad.blog'
version '1.0.0'

repositories {
    mavenCentral()
    maven {
        // Der Name kann beliebig gewählt werden
        name = "GitHubPackages"
        // Die URL des Repositories, in dem die Artefakte veröffentlicht wurden
        url = "https://maven.pkg.github.com/FlowSquad/devops-github-packages"
        credentials {
            // Die Zugangsdaten (weiter unten beschrieben)
            username = project.findProperty("gpr.user")
            password = project.findProperty("gpr.key")
        }
    }
}

dependencies {
    compile "io.flowsquad.blog:devops-github-packages-library:1.0.0"
}

Auch in diesem Modul müssen wir die Zugangsdaten bereitstellen, genauso wie wir das bereits für das library-Modul getan haben. Dafür kopieren wir die gradle.properties-Datei, die wir bereits erstellt haben, in das main-Modul.

Vorsicht: Ein Access-Token ist immer notwendig, um Artefakte herunterzuladen, auch wenn diese in einem öffentlichen Repository liegen!

Jetzt fehlt noch die Main-Klasse, in der wir die Utility-Methode aufrufen, die wir in der Library-Klasse erstellt haben:

package io.flowsquad.blog.devops.github.packages.main;

import io.flowsquad.blog.devops.github.packages.library.LibraryClass;

public class MainClass {
    public static void main(String[] args) {
        System.out.println(new LibraryClass().utilityMethod());
    }
}

Wenn wir die Anwendung nun starten, lädt Gradle das Artefakt von GitHub herunter, das wir vorher gebaut haben, baut damit das Main-Modul und führt es aus. Wenn alles klappt, sollten wir folgende Meldung auf der Konsole sehen:

console
Die Konsolen-Ausgabe

Wir haben jetzt erfolgreich ein Artefakt auf GitHub Packages veröffentlicht, es heruntergeladen und verwendet. Allerdings gibt es einige Fallstricke, die man kennen sollte, bevor man die Package Registry produktiv einsetzt:

  1. Snapshots funktionieren nicht \ Auch wenn in der Dokumentation steht, dass Snapshots unterstützt werden, konnten wir sie nicht zum Laufen bringen. Während die ersten Builds problemlos funktionieren, werden alte Versionen nicht gelöscht. Stattdessen werden immer neue Artefakte zum selben Release hinzugefügt, was irgendwann nicht mehr funktioniert. Ab diesem Zeitpunkt werden alte Snapshots geladen.
  2. Mehrere Artefakte pro Release funktionieren nicht\ Sobald man versucht, neben der Bibliothek selbst auch noch JavaDoc- und Sources-Artefakte hochzuladen, wird das Repository instabil. Selbst das Laden existierender Artefakte oder das Veröffentlichen neuer Bibliotheksversionen scheitern dann mit einem 400-Fehler. In unserem Fall half nur noch das Löschen des Artefakts oder Repositories.
  3. Öffentliche Versionen können nicht gelöscht werden\ Es ist zwar möglich, Artefakt-Versionen in privaten Repositories zu löschen, bei öffentlichen Repositories erlaubt GitHub das allerdings nicht. Deshalb sollte man sich vorher gut überlegen, was man veröffentlicht und was man für sich behält ;)
  4. Der Token benötigt die korrekten Scopes\ Der Personal Access Token, der zum Zugriff auf die Artefakte benötigt wird, muss exakt die oben aufgelisteten Scopes haben, damit alles ordnungsgemäß funktioniert. Falls einer davon fehlt, erhält man Fehlermeldungen, die häufig nicht auf das Fehlen einer Berechtigung schließen lassen!
  5. Dynamische Versionen verhindern das Release\ Falls man Spring Boot und die dynamischen Versionen verwendet, schlägt der Release fehl, weil die Versionen nicht statisch sind. Das hat zwar nicht direkt etwas mit GitHub Packages zu tun, ist aber trotzdem gut zu wissen. Um das zu beheben, muss man die build.gradle so anpassen, dass im Publishing-Block auch noch ein versionMapping vorhanden ist:
// Siehe oben

// Konfiguriert das Publishen
publishing {
    repositories {
        // Siehe oben
    }
    publications {
        gpr(MavenPublication) {
            from(components.java)
            // Behebt den Fehler mit den dynamischen Versionen von Spring Boot
            versionMapping {
                usage('java-api') {
                    fromResolutionOf('runtimeClasspath')
                }
                usage('java-runtime') {
                    fromResolutionResult()
                }
            }
        }
    }
}

Im zweiten Teil der Blog-Serie werden wir uns damit beschäftigen, wie wir GitHub Actions verwenden können, um unsere Build-Pipeline so zu automatisieren, dass immer automatisch die neueste Version veröffentlicht wird sobald wir neuen Code einchecken. Bis zum nächsten Mal!


Tags

#devops#github#gradle#pipeline
Previous Article
Vom Studenten zum Lehrbeauftragten
Alexander Praschek

Alexander Praschek

Co-Founder

Inhalte

1
Was ist GitHub Packages?
2
Wie kann ich es in mein Gradle-Projekt einbauen?

Ähnliche Beiträge

Docker-Images mit GitHub Actions und Google Cloud bauen
July 27, 2021
2 min
© 2024, All Rights Reserved.

Links

StartseiteLösungenBPM TrainingKarriereInsights

Social Media