ProHoster > Blog > administration > Brug af Gradle og Github Actions til at publicere Java Project til Sonatype Maven Central Repository
Brug af Gradle og Github Actions til at publicere Java Project til Sonatype Maven Central Repository
I denne artikel vil jeg tage et detaljeret kig på processen med at udgive en Java-artefakt fra bunden gennem Github Actions til Sonatype Maven Central Repository ved hjælp af Gradle-builderen.
Jeg besluttede at skrive denne artikel på grund af manglen på en normal tutorial på ét sted. Alle oplysninger skulle indsamles stykke for stykke fra forskellige kilder, i øvrigt ikke helt friske. Hvem bekymrer sig, velkommen under kat.
Oprettelse af et lager i Sonatype
Det første trin er at oprette et depot i Sonatype Maven Central. For dette går vi her, registrer og opret en ny opgave, og beder os om at oprette et lager. Vi kører i vores GroupId projekt, Projekt URL projekt link og SCM url et link til det versionskontrolsystem, som projektet er placeret i. GroupId her skal have formen com.example, com.example.domain, com.example.testsupport, og kan også være i form af et link til din github: github.com/ditbrugernavn -> io.github.ditbrugernavn. Under alle omstændigheder skal du bekræfte ejerskabet af dette domæne eller denne profil. Hvis du har angivet en github-profil, bliver du bedt om at oprette et offentligt lager med det ønskede navn.
Nogen tid efter bekræftelsen vil dit GroupId blive oprettet, og vi kan gå videre til næste trin, Gradle-konfiguration.
Konfigurerer Gradle
I skrivende stund fandt jeg ikke Gradle-plugins, der kunne hjælpe med at udgive artefakten. Det det eneste plugin jeg fandt, men forfatteren nægtede at støtte det yderligere. Derfor besluttede jeg at gøre alt selv, da det ikke er for svært at gøre dette.
Den første ting at finde ud af er Sonatypes krav til udgivelse. De er følgende:
Tilgængelighed af kildekoder og JavaDoc, dvs. skal deltage -sources.jar и-javadoc.jar filer. Som angivet i dokumentationen, hvis det ikke er muligt at levere kildekoder eller dokumentation, kan du lave en dummy -sources.jar eller -javadoc.jar med en simpel README indeni for at bestå testen.
Alle filer skal signeres med GPG/PGPOg .asc filen med signaturen skal inkluderes for hver fil.
tilgængelighed pom fil
Korrekte værdier groupId, artifactId и version. Versionen kan være en vilkårlig streng og kan ikke slutte med -SNAPSHOT
Tilstedeværelse påkrævet name, description и url
Tilstedeværelsen af oplysninger om licensen, udviklerne og versionskontrolsystemet
Det er de grundlæggende regler, der skal følges ved udgivelse. Fuld information tilgængelig her.
Vi implementerer disse krav i build.gradle fil. Lad os først tilføje alle de nødvendige oplysninger om udviklerne, licenserne, versionskontrolsystemet og også indstille url, navn og beskrivelse af projektet. Lad os skrive en simpel metode til dette:
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]'
}
}
}
}
}
Dernæst skal du angive det under den genererede samling -sources.jar и-javadoc.jar filer. Til dette afsnit java du skal tilføje følgende:
java {
withJavadocJar()
withSourcesJar()
}
Lad os gå videre til det sidste krav, opsætning af en GPG/PGP-signatur. For at gøre dette skal du tilslutte plugin'et signing:
plugins {
id 'signing'
}
Og tilføj et afsnit:
signing {
sign publishing.publications
}
Lad os endelig tilføje et afsnit 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
}
}
}
}
Her sonatypeBrugernavn и sonatypePassword variabler, der indeholder login og adgangskode oprettet under registrering på sonatype.org.
Altså finalen build.gradle vil se sådan ud:
Fuld build.gradle-kode
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]'
}
}
}
}
}
Jeg vil bemærke, at vi får versionen fra miljøvariablen: System.getenv('RELEASE_VERSION'). Vi vil blotlægge det under montering og tage det fra tagnavnet.
Generering af PGP-nøgler
Et af Sonatypes krav er, at alle filer skal signeres med en GPG/PGP-nøgle. For dette går vi her og download GnuPG-værktøjet til dit operativsystem.
Vi genererer et nøglepar: gpg --gen-key, indtast et brugernavn, e-mail, og indstil også en adgangskode.
Vi finder ud af det id vores nøgle med kommandoen: gpg --list-secret-keys --keyid-format short. Id vil blive angivet efter skråstreg, for eksempel: rsa2048/9B695056
Udgivelse af den offentlige nøgle til serveren https://keys.openpgp.org med kommandoen: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
Vi eksporterer den hemmelige nøgle til et vilkårligt sted, vi får brug for den i fremtiden: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Opsætning af Github Actions
Lad os gå videre til den sidste fase, opsætte build og auto-publicere ved hjælp af Github Actions.
Github Actions er en funktion, der giver dig mulighed for at automatisere arbejdsgangen ved at implementere en fuld CI/CD-cyklus. Byg, test og implementering kan udløses af forskellige hændelser: kode-push, oprettelse af udgivelser eller problemer. Denne funktionalitet er helt gratis for offentlige arkiver.
I dette afsnit viser jeg dig, hvordan du opsætter build- og push-kode og implementerer til Sonatype-lageret ved frigivelse, samt opsætter hemmeligheder.
Vi sætter hemmeligheder
Til automatisk samling og implementering har vi brug for en række hemmelige værdier, såsom nøgle-id, adgangskoden, som vi indtastede, da vi genererede nøglen, selve PGP-nøglen og Sonatype-login/adgangskode. Du kan indstille dem i en særlig sektion i lagerindstillingerne:
Vi indstiller følgende variable:
SONATYPE_USERNAME / SONATYPE_PASSWORD - login / adgangskode, som vi indtastede ved registrering hos Sonatype
SIGNING_KEYID/SIGNING_PASSWORD — PGP-nøgle-id og adgangskode indstillet under generering.
Jeg vil dvæle ved variablen GPG_KEY_CONTENTS mere detaljeret. Faktum er, at vi har brug for en privat PGP-nøgle til offentliggørelse. For at poste det i hemmelighederne brugte jeg instruktioner og derudover lavet en række handlinger.
Lad os kryptere vores nøgle med gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgved at indtaste en adgangskode. Det skal placeres i en variabel: SECRET_PASSPHRASE
Lad os oversætte den modtagne krypterede nøgle til en tekstform ved hjælp af base64: base64 9B695056.gpg.gpg > 9B695056.txt. Indholdet vil blive placeret i variablen: GPG_KEY_CONTENTS.
Byg setup, når du trykker kode og skaber PR
Først skal du oprette en mappe i roden af dit projekt: .github/workflows.
I den skal du markere filen, f.eks. gradle-ci-build.yml med følgende indhold:
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}}
Denne arbejdsgang vil blive udført, når der trykkes til filialer master, dev и testing, også når du opretter pull-anmodninger.
Jobafsnittet specificerer de trin, der skal udføres på de angivne hændelser. I dette tilfælde vil vi bygge på den nyeste version af ubuntu, bruge Java 8 og også bruge pluginnet til Gradle eskatos/gradle-command-action@v1som ved at bruge den seneste version af builderen kører de kommandoer, der er angivet i arguments. Variabler secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD det er de hemmeligheder, vi spurgte om tidligere.
Byggeresultaterne vil blive afspejlet på fanen Handlinger:
Implementer automatisk, når en ny udgivelse frigives
Lad os oprette en separat workflow-fil til autodeploy 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}}
Filen er næsten identisk med den forrige, bortset fra den hændelse, hvor den vil blive udløst. I dette tilfælde er dette tilfældet med oprettelse af et tag med et navn, der starter med v.
Før implementering skal vi udtrække PGP-nøglen fra hemmelighederne og placere den i roden af projektet, samt dekryptere den. Dernæst skal vi indstille en speciel miljøvariabel RELEASE_VERSION som vi henviser til gradle.build fil. Alt dette gøres i afsnittet Prepare to publish. Vi henter vores nøgle fra variabelen GPG_KEY_CONTENTS, oversætter den til en gpg-fil og dekrypterer den derefter ved at lægge den i filen secret.gpg.
Dernæst vender vi os til en speciel variabel GITHUB_REF, hvorfra vi kan få den version, som vi indstillede ved oprettelse af tagget. Denne variabel er relevant i dette tilfælde. refs/tags/v0.0.2 hvorfra vi afskærer de første 11 tegn for at få en bestemt version. Dernæst bruger vi standard Gradle-kommandoer til udgivelse: test publish
Kontrol af implementeringsresultater i Sonatype-lageret
Når udgivelsen er oprettet, bør arbejdsgangen beskrevet i det foregående afsnit starte. For at gøre dette skal du oprette en udgivelse:
tagnavnet skal starte med v. Hvis workflowet er fuldført efter at have klikket på Udgiv udgivelse, kan vi gå til Sonatype Nexus for at være sikker:
Artefakten dukkede op i Staging-lageret. Den vises med det samme i Åbn-status, derefter skal den manuelt overføres til Luk-status ved at trykke på den relevante knap. Efter at have kontrolleret, at alle krav er opfyldt, går artefakten i Luk-status og er ikke længere tilgængelig for ændring. I denne form ender den i MavenCentral. Hvis alt er i orden, kan du trykke på knappen Slip, og artefakten ender i Sonatype-depotet.
For at artefakten kan komme ind i MavenCentral, skal du bede om den i opgaven, som vi lavede helt i begyndelsen. Du behøver kun at gøre dette én gang, så vi udgiver for første gang. I efterfølgende tider er dette ikke påkrævet, alt vil blive synkroniseret automatisk. De aktiverede hurtigt synkronisering for mig, men det tog omkring 5 dage for artefakten at blive tilgængelig i MavenCentral.
Det er alt, vi har offentliggjort vores artefakt i MavenCentral.