I denne artikel vil jeg detaljeret gennemgå processen med at offentliggøre en Java-artefakt fra bunden via Github Actions til Sonatype Maven Central Repository ved hjælp af Gradle buildværktøjet.
Jeg besluttede at skrive denne artikel på grund af manglen på et ordentligt tutorial samlet ét sted. Al information måtte samles på kryds og tværs fra forskellige kilder, som ikke var helt opdaterede. Interessede er velkomne til at læse videre.
Oprettelse af et repository i Sonatype
Det første skridt er at oprette et repository i Sonatype Maven Central. For at gøre dette går vi til , registrerer os og opretter en ny opgave med anmodning om at oprette et repository for os. Vi indtaster vores GroupId for projektet, Projekt URL link til projektet og SCM url link til versionskontrolsystemet, hvor projektet findes. GroupId her bør være af formen com.example, com.example.domain, com.example.testsupport, eller det kan også være et link til din GitHub: -> io.github.yourusername. Under alle omstændigheder vil du skulle bekræfte ejerskabet af dette domæne eller profil. Hvis du angav en GitHub-profil, vil de anmode om at oprette et offentligt repository med det ønskede navn.
Efter et stykke tid efter bekræftelsen vil din GroupId blive oprettet, og vi kan gå videre til næste trin, konfiguration af Gradle.
Konfigurerer Gradle
På tidspunktet for skrivningen af denne artikel kunne jeg ikke finde plugins til Gradle, der kunne hjælpe med offentliggørelsen af artefakten. det eneste plugin, jeg fandt, men forfatteren har opgivet dets videre support. Derfor besluttede jeg at klare det hele selv, da det ikke er alt for besværligt.
Det første, der skal afklares, er Sonatype's krav til offentliggørelse. De er som følger:
- Tilstedeværelsen af kildekoder og JavaDoc, dvs. der skal være
-sources.jarog-javadoc.jarfiler. Som nævnt i dokumentationen, hvis det ikke er muligt at levere kildekoder eller dokumentation, kan man lave en tom fil-sources.jareller-javadoc.jarc med et simpelt README indeni for at bestå kontrol. - Alle filer skal være underskrevet med hjælp af
GPG/PGP, og.ascfilen, der indeholder underskriften, skal inkluderes for hver fil. - Tilstedeværelsen af
pomfilen - Korrekte værdier
groupId,artifactIdogversion. Versionen kan være en vilkårlig streng og må ikke slutte med-SNAPSHOT - Det er nødvendigt at have
name,descriptionogurl - Tilstedeværelsen af oplysninger om licens, udviklere og versionskontrolsystem
Dette er de grundlæggende regler, der skal overholdes ved offentliggørelse. Fulde oplysninger er tilgængelige .
Implementerer disse krav i build.gradle filen. For at komme i gang, lad os tilføje alle nødvendige oplysninger om udviklerne, licensen, versionskontrolsystemet, samt angive URL, navn og beskrivelse af projektet. For dette skal vi skrive en simpel metode:
def customizePom(pom) {
pom.withXml {
def root = asNode()
root.dependencies.removeAll { dep ->
dep.scope == "test"
}
root.children().last() + {
resolveStrategy = DELEGATE_FIRST
description 'Nogle beskrivelser af artefakten'
name 'Artefakt navn'
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@dev.ru'
}
}
}
}
}Dernæst skal vi angive, at der skal genereres -sources.jar og-javadoc.jar filer under bygningen. For dette i sektionen java skal der tilføjes følgende:
java {
withJavadocJar()
withSourcesJar()
}Lad os gå videre til det sidste krav, opsætning af GPG/PGP signatur. For dette vil vi tilføje plug-in signing:
plugins {
id 'signing'
}Og tilføje sektionen :
signing {
sign publishing.publications
}Endelig tilføj sektionen 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 sonatypeUsername og sonatypePassword variabler, der indeholder login og adgangskode, oprettet ved registrering på .
Således vil den endelige build.gradle se således ud:
Hele koden build.gradle
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 'Nogle beskrivelser af artefakt'
name 'Artefaktnavn'
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 'Apache Licens, 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 'UdviklerNavn'
email 'email@dev.dk'
}
}
}
}
}Jeg vil bemærke, at vi henter versionen fra miljøvariablen: System.getenv('RELEASE_VERSION'). Vi vil angive den under bygningen og tage den fra tagnavnet.
Generering af PGP-nøgle
Et af kravene fra Sonatype er, at alle filer skal signeres med en GPG/PGP-nøgle. Til dette går vi og downloader GnuPG-værktøjet til dit operativsystem.
- Vi genererer et nøglepar:
gpg --gen-key, indtaster brugernavn, e-mail og angiver et kodeord. - Vi finder ud af
idvores nøgle med kommandoen:gpg --list-secret-keys --keyid-format short. Id'et vil være angivet efter skråstregen, for eksempel: rsa2048/9B695056 - Offentliggør den offentlige nøgle på serveren med kommandoen:
gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056 - Eksporter den private nøgle til et vilkårligt sted, vi får brug for den senere:
gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Konfigurerer GitHub Actions
Lad os gå videre til den afsluttende fase, hvor vi konfigurerer bygningen og automatisk offentliggørelse ved hjælp af GitHub Actions.
Github Actions – en funktionalitet, der gør det muligt at automatisere arbejdsprocessen ved at implementere en fuld CI/CD-cyklus. Bygning, testning og implementering kan udløses af forskellige hændelser: kodepush, oprettelse af en udgivelse eller issues. Denne funktionalitet er helt gratis for offentlige repositories.
I dette afsnit vil jeg vise, hvordan man konfigurerer bygning og push af kode samt implementering i Sonatype-repository ved udgivelse af en release, samt opsætning af hemmeligheder.
Opsæt hemmeligheder
Til automatisk bygning og implementering har vi brug for en række hemmelige værdier, såsom nøgle-id, adgangskode, som vi indtastede ved generering af nøglen, selve PGP-nøglen samt login/adgangskode til Sonatype. Disse kan indstilles i et særligt afsnit i repository-indstillingerne:

Indstil følgende variabler:
- SONATYPE_USERNAME/SONATYPE_PASSWORD – login/adgangskode, som vi indtastede ved registrering i Sonatype.
- SIGNING_KEYID/SIGNING_PASSWORD – PGP-nøgle-id og adgangskode indstillet ved generering.
Jeg vil gerne fokusere lidt mere på variablen GPG_KEY_CONTENTS. Faktisk har vi brug for den private PGP-nøgle til offentliggørelse. For at placere den i hemmeligheder, benyttede jeg mig af og udførte desuden en række handlinger.
- Lad os kryptere vores nøgle med gpg:
gpg --symmetric --cipher-algo AES256 9B695056.gpg, indtast adgangskoden. Denne skal placeres i variablen: SECRET_PASSPHRASE - Lad os konvertere den krypterede nøgle til tekstformat ved hjælp af base64:
base64 9B695056.gpg.gpg > 9B695056.txt. Indholdet placeres i variablen: GPG_KEY_CONTENTS.
Konfiguration af bygning ved kodepush og oprettelse af PR
Først skal du oprette en mappe i roden af dit projekt: .github/workflows.
I denne mappe placeres en fil, for eksempel, 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 arbejdsproces vil blive udført ved push til grenene master, dev og testing, samt ved oprettelse af pull requests.
I jobs-sektionen er der angivet trin, der skal udføres ved de angivne hændelser. I dette tilfælde vil vi bygge på den seneste version af ubuntu, bruge Java 8, samt benytte en plugin til Gradle eskatos/gradle-command-action@v1, som ved anvendelse af den seneste version af builderen vil køre de angivne kommandoer. argumentsVariabler secrets.SONATYPE_USERNAME og secrets.SONATYPE_PASSWORD dette er hemmelighederne, vi har angivet tidligere.
Resultaterne af buildet vil blive vist under fanen Actions:

Autodeploy ved udgivelse af en ny version
For autodeply skal vi oprette en separat arbejdsprocessfil 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 ligner næsten den forrige undtagen for den hændelse, der vil udløse den. I dette tilfælde er det hændelsen af at oprette et tag med et navn, der begynder med v.
Før deployment skal vi trække PGP-nøglen fra hemmelighederne og placere den i roden af projektet samt dekryptere den. Derefter skal vi indstille en speciel miljøvariabel RELEASE_VERSION som vi refererer til i gradle.build filen. Alt dette gøres i sektionen Prepare to publish. Vi får vores nøgle fra variablen GPG_KEY_CONTENTS, konverterer den til en gpg-fil, dekrypterer den, og placerer den i filen secret.gpg.
Derefter refererer vi til en speciel variabel GITHUB_REF, hvorfra vi kan hente den version, vi angav, da vi oprettede tagget. Denne variabel har i dette tilfælde værdien refs/tags/v0.0.2 fra hvilken vi skærer de første 11 tegn for at få den specifikke version. Derefter bruger vi standard Gradle-kommandoer til publikation: test publish
Kontrol af resultaterne af deployment til Sonatype-repositoriet
Efter oprettelsen af en udgivelse skal arbejdsprocessen beskrevet i den forrige sektion starte. For at gøre dette opretter vi en udgivelse:

hvor navnet på tagget skal begynde med v. Hvis arbejdsprocessen kører korrekt efter at have klikket på Publish release, kan vi gå til for at bekræfte dette:

Artefakten er dukket op i Staging-repositoriet. Den vises straks med status Open, hvorefter den skal manuelt ændres til status Close ved at klikke på den relevante knap. Efter kontrol af, at alle krav er opfyldt, ændres artefakten til status Close og er ikke længere tilgængelig for ændringer. I denne form vil den blive sendt til MavenCentral. Hvis alt ser godt ud, kan du klikke på knappen Release, hvorefter artefakten vil blive sendt til Sonatype-repositoriet.
For at artefakten kan komme til MavenCentral, skal du anmode om det i opgaven, vi oprettede i starten. Dette skal kun gøres én gang, da vi offentliggør for første gang. Ved fremtidige udgivelser er dette ikke nødvendigt, alt vil synkronisere automatisk. Synkroniseringen blev aktiveret hurtigt for mig, men det tog omkring 5 dage, før artefakten blev tilgængelig i MavenCentral.
Det er alt, vi har offentliggjort vores artefakt i MavenCentral.
Nyttige links
- Lignende , kun offentliggørelse via maven
- Staging Sonatype
- Sonatype, hvor der skal oprettes en opgave
- repositoriet, hvor alt dette er indstillet
Kilde: habr.com
