Në këtë artikull, do të shqyrtoj në hollësi procesin e publikimit nga e para të një artefakti Java përmes Github Actions në Sonatype Maven Central Repository duke përdorur ndihmësin Gradle.
Vendosa ta shkruaj këtë artikull për shkak të mungesës së një tutoriali normal në një vend. Informacionin e duhur e kam mbledhur në copa nga burime të ndryshme, të cilat nuk ishin gjithmonë të freskëta. Ata që janë të interesuar, mirëseerdhët nën kat.
Krijimi i repositorit në Sonatype
Hapi i parë është të krijojmë një repozitor në Sonatype Maven Central. Për këtë shkojmë , regjistrohemi dhe krijojmë një detyrë të re, duke kërkuar të na krijohet një repozitor. Shkruajmë GroupId i projektit, URL-në e Projektit linkun për projektin dhe SCM url linkun për sistemin e kontrollit të versioneve, në të cilin ndodhet projekti. GroupId këtu duhet të jetë në formën com.example, com.example.domain, com.example.testsupport, ose mund të jetë në formën e një linku për Github-in tuaj: -> io.github.yourusername. Në çdo rast, do t'ju kërkohet të konfirmoni pronësinë e këtij domeni ose profili. Nëse keni cituar profilin e Github-it, do t'ju kërkohet të krijoni një repozitor publik me emrin përkatës.
Pas një kohe pas konfirmimit, GroupId juaj do të krijohet dhe ne mund të kalojmë në hapin e ardhshëm, konfigurimin e Gradle.
Konfigurojmë Gradle
Në momentin që po shkruaj këtë artikull, nuk kam gjetur plugin për Gradle që mund të ndihmojë në publikimin e artefaktit. plugin-i i vetëm që kam gjetur, por autori është tërhequr nga mbështetje e tij. Prandaj, vendosa ta bëj gjithçka vetë, duke patur parasysh se nuk është shumë e vështirë.
E para që duhet të zbulojmë, janë kërkesat e Sonatype për publikim. Ato janë si në vijim:
- Prania e kodit burimor dhe JavaDoc, dmth. duhet të jenë të pranishme
-sources.jardhe-javadoc.jarskedarët. Ashtu siç thuhet në dokumentacion, nëse nuk është e mundur të ofrohen kodet burimore ose dokumentacioni, mund të krijoni një skedar të zbrazët-sources.jarose-javadoc.jarme një README të thjeshtë brenda, për të kaluar verifikimin. - Të gjitha skedarët duhet të nënshkruhen me
GPG/PGP, dhe.ascskedari përmban nënshkrimin, duhet të përfshihet për çdo skedar. - Prania
pome skedarit - Vlerat e sakta
groupId,artifactIddheversion. Versioni mund të jetë një varg i rastësishëm dhe nuk mund të përfundojë-SNAPSHOT - Nevojitet të ketë
emri,descriptiondheurl - Prania e informacionit mbi licencat, zhvilluesit dhe sistemin e kontrollit të versioneve
Këto janë rregullat kryesore që duhet të respektohen gjatë publikimit. Informacioni i plotë është në dispozicion .
Realizojmë këto kërkesa në build.gradle skedari. Fillimisht, le të shtojmë të gjitha informacionet e nevojshme për zhvilluesit, licencat, sistemin e kontrollit të versioneve, si dhe të caktojmë URL-në, emrin dhe përshkrimin e projektit. Për këtë, shkruajmë një metoda të thjeshtë:
def customizePom(pom) {
pom.withXml {
def root = asNode()
root.dependencies.removeAll { dep ->
dep.scope == "test"
}
root.children().last() + {
resolveStrategy = DELEGATE_FIRST
description 'Disa përshkrim i artefaktit'
name 'Emri i Artefaktit'
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 'Licenca Apache, 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 'Emri i Zhvilluesit'
email 'email@dev.ru'
}
}
}
}
}Më pas, duhet të tregojmë se gjatë ndërtimit të krijohen -sources.jar dhe-javadoc.jar skedarët. Për këtë, në seksionin java duhet të shtojmë të mirat:
java {
withJavadocJar()
withSourcesJar()
}Të kalojmë në kërkesën e fundit, konfigurimin e nënshkrimit GPG/PGP. Për këtë, do të lidhim plugin-in signing:
plugins {
id 'signing'
}Dhe do të shtojmë seksionin:
signing {
sign publishing.publications
}Në fund, do të shtojmë seksionin 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
}
}
}
}Këtu sonatypeUsername dhe sonatypePassword variablat që përmbajnë emrin dhe fjalëkalimin, të krijuara gjatë regjistrimit në .
Kështu, kodi përfundimtar build.gradle do të duket si më poshtë:
Kodi i plotë 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 'Disa se e artefaktit'
name 'Emri i artefaktit'
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 'Licenca Apache, 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 'Emri i Dev'
email 'email@dev.ru'
}
}
}
}
}Dua të theksoj se versionin e marrim nga variabla e ambientit: System.getenv('RELEASE_VERSION'). Do ta vendosim gjatë ndërtimit dhe do ta marrim nga emri i etiketës.
Generimi i çelësit PGP
Një nga kërkesat e Sonatype është nënshkrimi i të gjitha skedarëve me çelësin GPG/PGP. Për këtë, shkojmë dhe shkarkojmë utilitarin GnuPG për sistemin e operimit të vet.
- Ndërtojmë çift çelësash:
gpg --gen-key, shkruajmë emrin e përdoruesit, e-mail-in, dhe vendosim një fjalëkalim. - Zbuloni
idçelësin tonë me komandën:gpg --list-secret-keys --keyid-format short. Id-ja do të jetë e shënuar pas shkronjës, për shembull: rsa2048/9B695056 - Publikoni çelësin publik në server komandën:
gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056 - Eksportoni çelësin sekret në një vend të rastësishëm, do na nevojitet më vonë:
gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Konfiguroni Github Actions
Tani do të kalojmë në fazën përfundimtare, do të konfigurojmë ndërtimin dhe publikimin automatik, duke përdorur Github Actions.
Github Actions â funksionaliteti qĂ« lejon automatizimin e procesit tĂ« punĂ«s, duke realizuar njĂ« cikĂ«l tĂ« plotĂ« CI/CD. NdĂ«rtimi, testimi dhe publikimi mund tĂ« thirren nga ngjarje tĂ« ndryshme: shtimi i kodit, krijimi i lĂ«shimit ose çështjeve. Ky funksionalitet Ă«shtĂ« plotĂ«sisht falas pĂ«r repo publik.
Në këtë seksion do të tregoj si të konfiguroj ndërtimin dhe shtimin e kodit dhe publikimin në repo Sonatype gjatë nxjerrjes së lëshimit, si dhe konfigurimin e sekreteve.
Caktoni sekretet
PĂ«r ndĂ«rtimin dhe publikimin automatik, na nevojiten njĂ« sĂ«rĂ« vlerash sekrete, si id e çelĂ«sit, fjalĂ«kalimi qĂ« vendosĂ«m gjatĂ« ndĂ«rtimit tĂ« çelĂ«sit, çelĂ«si PGP vetĂ« dhe gjithashtu login/fjalĂ«kalimi pĂ«r Sonatype. Mund tâi caktoni ato nĂ« njĂ« seksion tĂ« veçantĂ« nĂ« cilĂ«simet e repo:

Caktoni variablat e mëposhtme:
- SONATYPE_USERNAME/SONATYPE_PASSWORD â login/fjalĂ«kalimi qĂ« ne vendosĂ«m gjatĂ« regjistrimit nĂ« Sonatype
- SIGNING_KEYID/SIGNING_PASSWORD â id e çelĂ«sit PGP dhe fjalĂ«kalimi i vendosur gjatĂ« gjenerimit.
Dua të ndalem pak më gjatë te variabla GPG_KEY_CONTENTS. E vërteta është se për publikim na nevojitet çelësi i mbyllur PGP. Për ta vendosur në sekrete, unë përdora dhe realizova edhe një sërë veprimesh.
- Do të enkriptoj çelësin tonë me gpg:
gpg --symmetric --cipher-algo AES256 9B695056.gpg, duke vendosur një fjalëkalim. Kjo duhet të vendoset në variablën: SECRET_PASSPHRASE - Do ta konvertojmë çelësin e enkriptuar në format tekstual me base64:
base64 9B695056.gpg.gpg > 9B695056.txt. Përmbajtja do të vendoset në variablën: GPG_KEY_CONTENTS.
Konfigurimi i ndërtimit gjatë shtimit të kodit dhe krijimit të PR
Së pari, duhet të krijoni një dosje në rrënjën e projektit tuaj: .github/workflows.
Brenda saj vendosni një skedar, për shembull, gradle-ci-build.yml me përmbajtjen e mëposhtme:
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}}Ky proces pune do të ekzekutohet gjatë shtimit në degët master, dev dhe testing, gjithashtu gjatë krijimit të kërkesave të tërheqjes.
Në seksionin jobs janë hapat që duhet të realizohen për ngjarjet e specifikuara. Në këtë rast do të ndërtojmë në versionin më të fundit të ubuntu, do të përdorim Java 8, si dhe doemos plugin-in për Gradle eskatos/gradle-command-action@v1, i cili duke përdorur versionin më të fundit të ndërtuesit do të ekzekutojë komandat e shënuara në argumente. Variablat secrets.SONATYPE_USERNAME dhe secrets.SONATYPE_PASSWORD këto janë sekrete që kemi vendosur më parë.
Rezultatet e ndërtimit do të reflektohen në skedën Actions:

Autodeploy gjatë lëshimit të një versioni të ri
Për autodeploy do të krijojmë një skedë të veçantë punë 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}}Skeda është pothuajse identike me atë të mëparshmen, përveç ngjarjes kur do të aktivizohet. Në këtë rast, kjo është ngjarja e krijimit të një etikete me emrin që fillon me v.
Para se të bëjmë deploy, na nevojitet të nxjerrim çelësin PGP nga sekretet dhe ta vendosim atë në rrënjën e projektit, si dhe ta dekriptojmë atë. Pastaj na nevojitet të vendosim një ndryshore të veçantë ambienti RELEASE_VERSION për të cilën referohemi në gradle.build skedë. Të gjitha këto janë kryer në seksionin Prepare to publish. Ne nxjerrim çelësin tonë nga variabla GPG_KEY_CONTENTS, e transformojmë atë në skedën gpg, pastaj e dekriptojmë, duke e vendosur në skedën secret.gpg.
Më pas, ne referohemi në një variablë të veçantë GITHUB_REF, nga e cila mund të nxjerrim versionin që kemi caktuar kur krijuam etiketën. Kjo variabël në këtë rast ka vlerën refs/tags/v0.0.2 nga e cila ne presim 11 karakteret e para për të marrë saktësisht versionin. Më pas, përdorim komandat standarde të Gradle për publikim: test publish
Kontrolli i rezultateve të deploy-it në repository-në Sonatype
Pas krijimit të versionit, duhet të fillojë procesi i punës i përshkruar në seksionin e mëparshëm. Për këtë krijojmë një version:

duke bërë që emri i etiketës të fillojë me v. Nëse pas klikimit të Publish release, procesi i punës përfundon me sukses, ne mund të hyjmë në për ta verifikuar këtë:

Arti-fakti u shfaq në repository-në Staging. Ai fillimisht shfaqet me statusin Open, pastaj duhet ta kalosh dorazi në statusin Close, duke klikuar në butonin përkatës. Pas kontrollit të përmbushjes së të gjitha kërkesave, arti-fakti kalon në statusin Close dhe nuk është më i aksesueshëm për ndryshime. Në këtë formë, ai do të përfundojë në MavenCentral. Nëse gjithçka është në rregull, mund të klikoni butonin Release, në këtë rast arti-fakti do të kalojë në repository-në Sonatype.
Për të siguruar që arti-fakti të përfundojë në MavenCentral, duhet të kërkoni këtë në detyrën që krijuam në fillim. Kjo duhet të bëhet vetëm një herë, pasi po publikojmë për herë të parë. Herët e tjera, kjo nuk është e nevojshme; gjithçka do të sinkronizohet automatikisht. Më aktivizuan sinkronizimin shpejt, por që arti-fakti të bëhet i aksesueshëm në MavenCentral kaluan rreth 5 ditë.
Këtu është mbyllur, kemi publikuar arti-faktin tonë në MavenCentral.
Linqe të dobishme
- Një ngjashmëri , vetëm publikimi përmes maven
- Staging Sonatype
- Sonatype, në të cilën duhet të krijoni një detyrë
- repository, ku është e gjithçka e konfiguruar
Burimi: habr.com
