ProHoster > blog > administratie > Gradle- en Github-acties gebruiken om Java-project te publiceren naar Sonatype Maven Central Repository
Gradle- en Github-acties gebruiken om Java-project te publiceren naar Sonatype Maven Central Repository
In dit artikel wil ik uitgebreid ingaan op het proces van het vanaf het begin publiceren van een Java-artefact via Github Actions naar de Sonatype Maven Central Repository met behulp van de Gradle-builder.
Ik besloot dit artikel te schrijven vanwege het ontbreken van een normale tutorial op één plek. Alle informatie moest stuk voor stuk uit verschillende bronnen worden verzameld, bovendien niet helemaal vers. Wat maakt het uit, welkom onder kat.
Een repository maken in Sonatype
De eerste stap is het maken van een repository in Sonatype Maven Central. Hiervoor gaan we hier, registreer en maak een nieuwe taak aan en vraag ons om een repository te maken. We rijden in onze Groeps-ID projecteren, Project-URL projectlink en SCM-URL een koppeling naar het versiebeheersysteem waarin het project zich bevindt. Groeps-ID hier zou de vorm com.example, com.example.domain, com.example.testsupport moeten hebben, en kan ook de vorm hebben van een link naar je github: github.com/uwgebruikersnaam -> io.github.uwgebruikersnaam. In elk geval moet u het eigendom van dit domein of dit profiel verifiëren. Als je een github-profiel hebt opgegeven, wordt je gevraagd om een openbare repository met de gewenste naam te maken.
Enige tijd na bevestiging wordt uw GroupId aangemaakt en kunnen we doorgaan naar de volgende stap, Gradle-configuratie.
Gradle configureren
Op het moment van schrijven heb ik geen Gradle-plug-ins gevonden die kunnen helpen bij het publiceren van het artefact. Het de enige plug-in die ik vond, maar de auteur weigerde deze verder te ondersteunen. Daarom besloot ik alles zelf te doen, aangezien het niet zo moeilijk is om dit te doen.
Het eerste dat u moet uitzoeken, zijn de publicatievereisten van Sonatype. Dit zijn de volgende:
Beschikbaarheid van broncodes en JavaDoc, dwz. moet aanwezig zijn -sources.jar и-javadoc.jar bestanden. Zoals vermeld in de documentatie, als het niet mogelijk is om broncodes of documentatie te verstrekken, kunt u een dummy maken -sources.jar of -javadoc.jar met een eenvoudige README erin om de test te halen.
Alle bestanden moeten worden ondertekend met GPG/PGPEn .asc het bestand met de handtekening moet voor elk bestand worden toegevoegd.
beschikbaarheid pom het dossier
Correcte waarden groupId, artifactId и version. De versie kan een willekeurige tekenreeks zijn en kan niet eindigen op -SNAPSHOT
Aanwezigheid vereist name, description и url
De aanwezigheid van informatie over de licentie, ontwikkelaars en het versiebeheersysteem
Dit zijn de basisregels die moeten worden gevolgd bij het publiceren. Volledige informatie beschikbaar hier.
We implementeren deze eisen in build.gradle bestand. Laten we eerst alle benodigde informatie over de ontwikkelaars, licenties, versiebeheersysteem toevoegen en ook de url, naam en beschrijving van het project instellen. Laten we hiervoor een eenvoudige methode schrijven:
def customizePom(pom) {
pom.withXml {
def root = asNode()
root.dependencies.removeAll { dep ->
dep.scope == "test"
}
root.children().last() + {
resolveStrategy = DELEGATE_FIRST
description 'Some description of artifact'
name 'Artifct name'
url 'https://github.com/login/projectname'
organization {
name 'com.github.login'
url 'https://github.com/login'
}
issueManagement {
system 'GitHub'
url 'https://github.com/login/projectname/issues'
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
scm {
url 'https://github.com/login/projectname'
connection 'scm:https://github.com/login/projectname.git'
developerConnection 'scm:git://github.com/login/projectname.git'
}
developers {
developer {
id 'dev'
name 'DevName'
email '[email protected]'
}
}
}
}
}
Vervolgens moet u dat specificeren tijdens de gegenereerde assemblage -sources.jar и-javadoc.jar bestanden. Voor dit gedeelte java je moet het volgende toevoegen:
java {
withJavadocJar()
withSourcesJar()
}
Laten we verder gaan met de laatste vereiste, het instellen van een GPG/PGP-handtekening. Sluit hiervoor de plug-in aan signing:
plugins {
id 'signing'
}
En voeg een sectie toe:
signing {
sign publishing.publications
}
Laten we tot slot een sectie toevoegen publishing:
publishing {
publications {
mavenJava(MavenPublication) {
customizePom(pom)
groupId group
artifactId archivesBaseName
version version
from components.java
}
}
repositories {
maven {
url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
credentials {
username sonatypeUsername
password sonatypePassword
}
}
}
}
Hier sonatypeGebruikersnaam и sonatypeWachtwoord variabelen die de gebruikersnaam en het wachtwoord bevatten die zijn gemaakt tijdens de registratie op sonatype.org.
Aldus de finale build.gradle zal er zo uitzien:
Volledige build.gradle-code
plugins {
id 'java'
id 'maven-publish'
id 'signing'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
withJavadocJar()
withSourcesJar()
}
group 'io.github.githublogin'
archivesBaseName = 'projectname'
version = System.getenv('RELEASE_VERSION') ?: "0.0.1"
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
}
test {
useJUnitPlatform()
}
jar {
from sourceSets.main.output
from sourceSets.main.allJava
}
signing {
sign publishing.publications
}
publishing {
publications {
mavenJava(MavenPublication) {
customizePom(pom)
groupId group
artifactId archivesBaseName
version version
from components.java
}
}
repositories {
maven {
url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
credentials {
username sonatypeUsername
password sonatypePassword
}
}
}
}
def customizePom(pom) {
pom.withXml {
def root = asNode()
root.dependencies.removeAll { dep ->
dep.scope == "test"
}
root.children().last() + {
resolveStrategy = DELEGATE_FIRST
description 'Some description of artifact'
name 'Artifct name'
url 'https://github.com/login/projectname'
organization {
name 'com.github.login'
url 'https://github.com/githublogin'
}
issueManagement {
system 'GitHub'
url 'https://github.com/githublogin/projectname/issues'
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
scm {
url 'https://github.com/githublogin/projectname'
connection 'scm:https://github.com/githublogin/projectname.git'
developerConnection 'scm:git://github.com/githublogin/projectname.git'
}
developers {
developer {
id 'dev'
name 'DevName'
email '[email protected]'
}
}
}
}
}
Ik wil opmerken dat we de versie krijgen van de omgevingsvariabele: System.getenv('RELEASE_VERSION'). We zullen het tijdens de montage blootleggen en het uit de tagnaam halen.
Generatie van PGP-sleutels
Een van de vereisten van Sonatype is dat alle bestanden zijn ondertekend met een GPG/PGP-sleutel. Hiervoor gaan we hier en download het GnuPG-hulpprogramma voor uw besturingssysteem.
We genereren een sleutelpaar: gpg --gen-key, voer een gebruikersnaam en e-mailadres in en stel ook een wachtwoord in.
We komen er achter id onze sleutel met het commando: gpg --list-secret-keys --keyid-format short. Id wordt gespecificeerd na de schuine streep, bijvoorbeeld: rsa2048/9B695056
Publicatie van de openbare sleutel naar de server https://keys.openpgp.org met het commando: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
We exporteren de geheime sleutel naar een willekeurige plaats, we zullen deze in de toekomst nodig hebben: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Github-acties instellen
Laten we doorgaan naar de laatste fase, de build instellen en automatisch publiceren met Github Actions.
Github Actions is een functie waarmee u de workflow kunt automatiseren door een volledige CI/CD-cyclus te implementeren. Het bouwen, testen en implementeren kan worden geactiveerd door verschillende gebeurtenissen: het pushen van code, het maken van een release of problemen. Deze functionaliteit is helemaal gratis voor openbare repositories.
In deze sectie laat ik je zien hoe je build- en pushcode instelt en implementeert in de Sonatype-repository bij release, en hoe je geheimen instelt.
We stellen geheimen
Voor automatische montage en implementatie hebben we een aantal geheime waarden nodig, zoals de sleutel-ID, het wachtwoord dat we hebben ingevoerd bij het genereren van de sleutel, de PGP-sleutel zelf en de Sonatype login/wachtwoord. Je kunt ze instellen in een speciaal gedeelte in de repository-instellingen:
We stellen de volgende variabelen in:
SONATYPE_USERNAME / SONATYPE_PASSWORD - login / wachtwoord dat we hebben ingevoerd bij het registreren bij Sonatype
SIGNING_KEYID/SIGNING_PASSWORD — PGP-sleutel-ID en wachtwoord ingesteld tijdens het genereren.
Ik wil dieper ingaan op de variabele GPG_KEY_CONTENTS. Feit is dat we voor publicatie een private PGP-sleutel nodig hebben. Om het in de geheimen te plaatsen, gebruikte ik instructies en voerde daarnaast een aantal acties uit.
Laten we onze sleutel coderen met gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgdoor een wachtwoord in te voeren. Het moet in een variabele worden geplaatst: SECRET_PASSPHRASE
Laten we de ontvangen versleutelde sleutel in een tekstvorm vertalen met behulp van base64: base64 9B695056.gpg.gpg > 9B695056.txt. De inhoud wordt geplaatst in de variabele: GPG_KEY_CONTENTS.
Bouw setup bij het pushen van code en het creëren van PR
Eerst moet u een map maken in de hoofdmap van uw project: .github/workflows.
Markeer daarin het bestand, bijvoorbeeld gradle-ci-build.yml met de volgende inhoud:
name: build
on:
push:
branches:
- master
- dev
- testing
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Build with Gradle
uses: eskatos/gradle-command-action@v1
with:
gradle-version: current
arguments: build -PsonatypeUsername=${{secrets.SONATYPE_USERNAME}} -PsonatypePassword=${{secrets.SONATYPE_PASSWORD}}
Deze workflow wordt uitgevoerd bij het pushen naar branches master, dev и testing, ook bij het maken van pull-aanvragen.
De sectie Jobs specificeert de stappen die moeten worden uitgevoerd op de opgegeven gebeurtenissen. In dit geval bouwen we voort op de nieuwste versie van ubuntu, gebruiken we Java 8 en gebruiken we ook de plug-in voor Gradle eskatos/gradle-command-action@v1die, met behulp van de nieuwste versie van de builder, de opdrachten zal uitvoeren die zijn gespecificeerd in arguments. Variabelen secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD dit zijn de geheimen die we eerder hebben gevraagd.
De buildresultaten worden weergegeven op het tabblad Acties:
Automatisch implementeren wanneer een nieuwe release wordt uitgebracht
Laten we een apart werkstroombestand maken voor automatische implementatie gradle-ci-publish.yml:
name: publish
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Prepare to publish
run: |
echo '${{secrets.GPG_KEY_CONTENTS}}' | base64 -d > publish_key.gpg
gpg --quiet --batch --yes --decrypt --passphrase="${{secrets.SECRET_PASSPHRASE}}"
--output secret.gpg publish_key.gpg
echo "::set-env name=RELEASE_VERSION::${GITHUB_REF:11}"
- name: Publish with Gradle
uses: eskatos/gradle-command-action@v1
with:
gradle-version: current
arguments: test publish -Psigning.secretKeyRingFile=secret.gpg -Psigning.keyId=${{secrets.SIGNING_KEYID}} -Psigning.password=${{secrets.SIGNING_PASSWORD}} -PsonatypeUsername=${{secrets.SONATYPE_USERNAME}} -PsonatypePassword=${{secrets.SONATYPE_PASSWORD}}
Het bestand is bijna identiek aan het vorige, behalve de gebeurtenis waarin het wordt geactiveerd. In dit geval is dit het geval waarbij een tag wordt gemaakt met een naam die begint met v.
Voor de implementatie moeten we de PGP-sleutel uit de geheimen halen en in de hoofdmap van het project plaatsen, en deze ook decoderen. Vervolgens moeten we een speciale omgevingsvariabele instellen RELEASE_VERSION waarnaar we verwijzen gradle.build bestand. Dit alles gebeurt in de sectie Prepare to publish. We halen onze sleutel uit de variabele GPG_KEY_CONTENTS, vertalen deze naar een gpg-bestand en decoderen deze vervolgens door deze in het bestand te plaatsen secret.gpg.
Vervolgens gaan we naar een speciale variabele GITHUB_REF, waaruit we de versie kunnen halen die we hebben ingesteld bij het maken van de tag. Deze variabele is in dit geval relevant. refs/tags/v0.0.2 waarvan we de eerste 11 tekens hebben afgesneden om een specifieke versie te krijgen. Vervolgens gebruiken we de standaard Gradle-commando's voor publicatie: test publish
Implementatieresultaten controleren in de Sonatype-repository
Nadat de release is gemaakt, zou de workflow moeten starten die in de vorige sectie is beschreven. Maak hiervoor een release aan:
de tagnaam moet beginnen met v. Als de workflow na het klikken op Release publiceren is voltooid, kunnen we naar Sonatype Nexus om er zeker van te zijn:
Het artefact verscheen in de Staging-repository. Het verschijnt onmiddellijk in de Open-status, daarna moet het handmatig worden overgebracht naar de Close-status door op de juiste knop te drukken. Nadat is gecontroleerd of aan alle vereisten is voldaan, krijgt het artefact de status Sluiten en is het niet langer beschikbaar voor wijziging. In deze vorm komt het terecht in MavenCentral. Als het goed is, kun je op de knop drukken Sinds, en het artefact komt terecht in de Sonatype-repository.
Om het artefact in MavenCentral te krijgen, moet je erom vragen in de taak die we aan het begin hebben gemaakt. Je hoeft dit maar één keer te doen, dus we publiceren voor het eerst. In latere tijden is dit niet nodig, alles wordt automatisch gesynchroniseerd. Ze hebben de synchronisatie snel voor me ingeschakeld, maar het duurde ongeveer 5 dagen voordat het artefact beschikbaar kwam in MavenCentral.
Dat is alles, we hebben ons artefact gepubliceerd in MavenCentral.
Nuttige links
Vergelijkbaar artikel, alleen publiceren via maven