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.
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.
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
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:
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:
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:
// 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!
Rechtliches