Në këtë artikull, do të shqyrtoj procesin e publikimit nga e para të një artefakti Java përmes Github Actions në Repositorin Qendror të Maven në Sonatype duke përdorur ndihmësin Gradle.
E shkrova këtë artikull për shkak të mungesës së një tutoriali të mirë në një vend. Të gjitha informacionet duhej të mblidheshin në copa nga burime të ndryshme, dhe ato nuk ishin gjithmonë të freskëta. Nëse jeni të interesuar, ju lutem shihni më poshtë.
Krijimi i Repositorit në Sonatype
Hapi i parë është të krijojmë një repository në Sonatype Maven Central. Për këtë, shkojmë , regjistrohemi dhe krijojmë një detyrë të re, me kërkesën për të krijuar një repository për ne. Shkruajmë GroupId projekti, URL e Projektit linkun për projektin dhe SCM url linkun për sistemin e kontrollit të versioneve, ku ndodhet projekti. GroupId këtu duhet të jetë në formatin com.example, com.example.domain, com.example.testsupport, gjithashtu mund të jetë në formën e një lidhjeje në 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 treguar profilin e github-it, do t'ju kërkojnë të krijoni një repository publik me emrin e nevojshëm.
Pas disa kohësh pas konfirmimit, GroupId juaj do të krijohet dhe mund të kalojmë në hapin tjetër, konfigurimin e Gradle.
Konfigurojmë Gradle
Në momentin e shkruarjes së artikullit, nuk gjetëm plugin për Gradle që mund të ndihmonte me publikimin e artefaktit. plugin-i i vetëm që gjetëm, megjithatë autori e hoqi nga mbështetja e mëtejshme. Prandaj, vendosa ta bëj gjithçka vetë, të cilat nuk ishin shumë të vështira.
E para që duhet të shqyrtojmë janë kërkesat e Sonatype për publikimin. Ato janë si vijon:
- Prania e kodit burimor dhe JavaDoc, dmth. duhet të jenë të pranishme
-sources.jardhe-javadoc.jarskedarët. Siç thotë dokumentacioni, nëse nuk mund të ofrohet kodi burimor ose dokumentacioni, mund të krijoni një boshllëk-sources.jarose-javadoc.jarme një README të thjeshtë brenda, për të kaluar verifikimin. - Të gjitha skedarët duhet të jenë të nënshkruar me
GPG/PGP, dhe.ascskedari që përmban nënshkrimin duhet të përfshihet për çdo skedar. - Prania
pomskedare - Vlerat e sakta
groupId,artifactIddheversion. Versioni mund të jetë një varg i rastësishëm dhe nuk mund të përfundojë-SNAPSHOT - Prania e
emri,descriptiondheurl - Prania e informacionit për 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 .
Implementojmë këto kërkesa në build.gradle Në fillim, le të shtojmë të gjitha informacionet e nevojshme rreth zhvilluesve, licencës, sistemit të kontrollit të versioneve, si dhe të caktojmë URL-në, emrin dhe përshkrimin e projektit. Për këtë, do të shkruajmë një metodë 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 artifactit'
name 'Emri i Artifactit'
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ë caktojmë që gjatë ndërtimit të gjenerohen -sources.jar dhe-javadoc.jar skedarët. Për këtë, në seksionin java duhet të shtojmë sa vijon:
java {
withJavadocJar()
withSourcesJar()
}Të kalojmë në kërkesën e fundit, konfigurimin e nënshkrimit GPG/PGP. Për këtë do të aktivizojmë add-on-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 e përdoruesit dhe fjalëkalimin, të krijuara gjatë regjistrimit në .
Kështu, kodin 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 'Dëshmi e ndonjë artefakt'
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, Versioni 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 Devit'
email 'email@dev.sq'
}
}
}
}
}Dua të theksoj se versionin e marrim nga variabla e ambientit: System.getenv('RELEASE_VERSION'). Ne do ta vendosim atë 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ë gjithë skedareve me çelësin GPG/PGP. Për këtë, shkojmë dhe shkarkojmë mjetin GnuPG për sistemin tonë operativ.
- Krijojmë një palë çelësash:
gpg --gen-key, futim emrin e përdoruesit, e-mailin, dhe përcaktojmë një fjalëkalim. - Kërkojmë
idçelësin tonë me komandën:gpg --list-secret-keys --keyid-format short. Id do të jetë i shfaqur pas shkronjës, për shembull: rsa2048/9B695056 - Publikojmë çelësin publik në server me komandën:
gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056 - Eksportojmë çelësin sekret në një vend të rastësishëm, do na nevojitet më vonë:
gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Konfigurojmë Github Actions
Të kalojmë në hapin përfundimtar, t'i konfigurojmë ndërtimet dhe publikimin automatik, duke përdorur Github Actions.
Github Actions – funksioni që mundëson automatizimin e procesit të punës, duke realizuar ciklin e plotë CI/CD. Ndërtimi, testimi dhe shpërndarja mund të aktivizohen nga ngjarje të ndryshme: shtimi i kodit, krijimi i një versioni ose çështjeve. Ky funksionalitet është krejtësisht falas për depozitat publike.
Në këtë seksion do të tregoj si të konfiguroj ndërtimin dhe shtimin e kodit dhe shpërndarjen në depozitën Sonatype gjatë lëshimit të versionit, si dhe konfigurimin e sekreteve.
Vendosim sekretet
Për ndërtimin automatik dhe shpërndarjen na nevojiten disa vlera sekrete, si id e çelësit, fjalëkalimi që përdorëm gjatë gjenerimit të çelësit, vetë çelësi PGP, si dhe përdoruesi/fjalëkalimi për Sonatype. Ato mund të vendosen në një seksion të veçantë në cilësimet e depozitës:

Vendosim variablat e mëposhtme:
- SONATYPE_USERNAME/SONATYPE_PASSWORD – përdoruesi/fjalëkalimi që përdorëm gjatë regjistrimit në Sonatype
- SIGNING_KEYID/SIGNING_PASSWORD – id e çelësit PGP dhe fjalëkalimi i vendosur gjatë gjenerimit.
Në varg të GPG_KEY_CONTENTS do të ndalem më në detaje. Arsyeja është se për publikimin na nevojitet çelësi privat PGP. Për ta vendosur atë në sekrete, kam përdorur dhe gjithashtu kam bërë disa veprime të tjera.
- Do ta enkriptojmë çelësin tonë me gpg:
gpg --symmetric --cipher-algo AES256 9B695056.gpg, duke futur fjalëkalimin. Ai duhet të vendoset në variablin: SECRET_PASSPHRASE - Do ta kthejmë çelësin e enkriptuar në një format tekstual duke përdorur base64:
base64 9B695056.gpg.gpg > 9B695056.txt. Përmbajtja do të vendoset në variablin: GPG_KEY_CONTENTS.
Konfigurimi i ndërtimit gjatë shtimit të kodit dhe krijimit të PR
Fillimisht duhet të krijoni një dosje në rrënjën e projektit tuaj: .github/workflows.
Në të vendosni një skedë, 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 do të ekzekutohet gjatë shtimit në degët master, dev dhe testimi, gjithashtu gjatë krijimit të kërkesave të tërheqjes.
Në seksionin jobs janë të renditura hapat që duhet të përfundojnë sipas ngjarjeve të përcaktuara. Në këtë rast do të bëjmë ndërtimin në versionin më të fundit të ubuntu, do të përdorim Java 8, si dhe do të përdorim një plugin 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 cekura në arguments. Variablat secrets.SONATYPE_USERNAME dhe secrets.SONATYPE_PASSWORD këto janë sekretet që kemi caktuar më parë.
Rezultatet e ndërtimit do të reflektohen në skedën Actions:

Auto-deploy kur lansohet një version i ri
Për autodeploy do të krijojmë një skedar të veçantë të procesit të punës 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}}Skedari është praktikisht identik me të mëparshmin përveç ngjarjes, kur do të aktivizohet. Në këtë rast, kjo ngjarje është krijimi i një etike te emri që fillon me v.
Para se të bëjmë deploy, na nevojitet të nxjerrim çelësin PGP nga sekretet dhe ta vendosim në rrënjën e projektit, gjithashtu ta dekriptojmë atë. Pastaj, na nevojitet të vendosim një variabël të veçantë mjedisi RELEASE_VERSION në të cilën referohemi në gradle.build skedari. Të gjitha këto bëhen në seksionin Prepare to publish. Ne marrim çelësin tonë nga variabla GPG_KEY_CONTENTS, e kthejmë në skedarin gpg, pastaj e dekriptojmë atë, duke e vendosur në skedarin secret.gpg.
Pastaj ne referohemi në një variabël të veçantë GITHUB_REF, nga e cila mund të nxjerrim versionin që kemi caktuar gjatë krijimit të etiketës. Kjo variablë në këtë rast ka vlerën refs/tags/v0.0.2 nga e cila ne heqim 11 karakteret e para, për të marrë saktësisht versionin. Pastaj përdorim komandat standarde Gradle për publikimin: test publish
Kontrolloni rezultatet e deploy në depoja Sonatype
Pas krijimit të versionit duhet të aktivizohet procesi i punës, i përshkruar në seksionin e mëparshëm. Për këtë krijojmë një version:

me emrin e etiketës që duhe 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 të u siguruar për këtë:

Artefakti u shfaq në repozitorinë Staging. Ai shfaqet menjëherë me statusin Open, pastaj duhet të transferohet manualisht në statusin Close duke klikuar butonin përkatës. Pas shqyrtimit të përmbushjes së të gjitha kërkesave, artefakti kalon në statusin Close dhe nuk është më i disponueshëm për ndryshime. Në këtë formë ai do të çojë në MavenCentral. Nëse gjithçka është në rregull, mund të klikoni butonin Release, ndërkohë artefakti do të kalojë në repozitorin Sonatype.
Për të siguruar që artefakti të kalojë në MavenCentral, duhet të kërkoni këtë në detyrën që krijuam në fillim. Kjo duhet bërë vetëm një herë, sepse ne po publikojmë për herë të parë. Herët e tjera nuk është e nevojshme, gjithçka do të sinkronizohet automatikisht. Më shkurt aktivizuan sinkronizimin për mua, por që artefakti të bëhet i disponueshëm në MavenCentral kaloi rreth 5 ditë.
Këtu përfundon, ne publikojmë artefaktin tonë në MavenCentral.
Useful links
- E ngjashme , vetëm publikimi përmes maven
- Staging Sonatype
- Sonatype, ku është e nevojshme të krijohet një detyrë
- repozitore, ku gjithçka është e konfiguruar
Burimi: habr.com
