ProHoster > блог > Администрација > Користење Gradle и Github Actions за објавување Java Project во Sonatype Maven Central Repository
Користење Gradle и Github Actions за објавување Java Project во Sonatype Maven Central Repository
Во оваа статија, сакам детално да го разгледам процесот на објавување артефакт Јава од нула преку Github Actions до централното складиште на Sonatype Maven со помош на градителот Gradle.
Решив да ја напишам оваа статија поради недостаток на нормален туторијал на едно место. Сите информации требаше да се собираат дел по дел од различни извори, згора на тоа, не сосема свежи. Кој се грижи, добредојде под мачка.
Создавање складиште во Sonatype
Првиот чекор е да се создаде складиште во Sonatype Maven Central. За ова одиме тука, регистрирајте се и креирајте нова задача, барајќи од нас да создадеме складиште. Возиме во нашите Групна ИД проект, URL на проект врска со проектот и УРЛ на SCM врска до системот за контрола на верзијата во кој се наоѓа проектот. Групна ИД тука треба да биде од формата com.example, com.example.domain, com.example.testsupport, а може да биде и во форма на врска до вашиот github: github.com/вашето корисничко име -> io.github.вашето корисничко име. Во секој случај, ќе треба да ја потврдите сопственоста на овој домен или профил. Ако наведовте профил на github, ќе биде побарано да креирате јавно складиште со саканото име.
Некое време по потврдата, вашиот GroupId ќе биде креиран и можеме да преминеме на следниот чекор, конфигурација на Gradle.
Конфигурирање Gradle
Во моментот на пишување, не најдов Gradle приклучоци кои би можеле да помогнат при објавувањето на артефактот. Тоа единствениот приклучок што го најдов, сепак, авторот одби дополнително да го поддржи. Затоа, решив да направам сè сам, бидејќи не е премногу тешко да се направи ова.
Првото нешто што треба да се сфати е барањата на Sonatype за објавување. Тие се следните:
Достапност на изворни кодови и JavaDoc, т.е. мора да присуствуваат -sources.jar и-javadoc.jar датотеки. Како што е наведено во документацијата, ако не е можно да се обезбедат изворни кодови или документација, можете да направите кукла -sources.jar или -javadoc.jar со едноставно README внатре за да го положите тестот.
Сите датотеки мора да бидат потпишани со GPG/PGPИ .asc датотеката што го содржи потписот мора да биде вклучена за секоја датотека.
достапност pom датотека
Точни вредности groupId, artifactId и version. Верзијата може да биде произволна низа и не може да завршува со -SNAPSHOT
Потребно е присуство name, description и url
Присуство на информации за лиценцата, програмерите и системот за контрола на верзијата
Ова се основните правила што мора да се почитуваат при објавувањето. Достапни се целосни информации тука.
Ние ги имплементираме овие барања во build.gradle датотека. Прво, да ги додадеме сите потребни информации за програмерите, лиценците, системот за контрола на верзии, а исто така да ги поставиме URL-то, името и описот на проектот. Ајде да напишеме едноставен метод за ова:
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]'
}
}
}
}
}
Следно, треба да го наведете тоа за време на собранието генерирано -sources.jar и-javadoc.jar датотеки. За овој дел java треба да го додадете следново:
java {
withJavadocJar()
withSourcesJar()
}
Ајде да преминеме на последното барање, поставување на GPG/PGP потпис. За да го направите ова, поврзете го приклучокот signing:
plugins {
id 'signing'
}
И додадете дел:
signing {
sign publishing.publications
}
Конечно, да додадеме дел 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
}
}
}
}
Тука sonatypeКорисничко име и sonatypePassword променливи кои ги содржат најавата и лозинката создадени при регистрација на sonatype.org.
Така финалето build.gradle ќе изгледа вака:
Целосна 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 '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]'
}
}
}
}
}
Сакам да забележам дека ја добиваме верзијата од променливата на околината: System.getenv('RELEASE_VERSION'). Ќе го изложиме за време на склопувањето и ќе го земеме од името на ознаката.
Генерирање на PGP клучеви
Едно од барањата на Sonatype е сите датотеки да бидат потпишани со клуч GPG/PGP. За ова одиме тука и преземете ја алатката GnuPG за вашиот оперативен систем.
Ние генерираме пар клучеви: gpg --gen-key, внесете корисничко име, е-пошта, а исто така поставете лозинка.
Дознаваме id нашиот клуч со командата: gpg --list-secret-keys --keyid-format short. ИД ќе биде наведен по коса црта, на пример: rsa2048/9B695056
Објавување на јавниот клуч на серверот https://keys.openpgp.org команда: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
Го извезуваме тајниот клуч на произволно место, ќе ни треба во иднина: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Поставување Github Actions
Ајде да продолжиме до последната фаза, да го поставиме изградбата и автоматски да објавуваме со помош на Github Actions.
Github Actions е карактеристика што ви овозможува да го автоматизирате работниот тек со имплементирање на целосен циклус CI / CD. Изградбата, тестирањето и распоредувањето може да бидат активирани од различни настани: притискање на кодот, создавање ослободување или проблеми. Оваа функционалност е апсолутно бесплатна за јавните складишта.
Во овој дел, ќе ви покажам како да поставите build и туркање код и да го распоредите во складиштето Sonatype по објавувањето, како и да поставите тајни.
Ние поставуваме тајни
За автоматско склопување и распоредување, потребни ни се голем број тајни вредности, како што се идентификацијата на клучот, лозинката што ја внесовме при генерирањето на клучот, самиот клуч PGP и најава/лозинка на Sonatype. Можете да ги поставите во посебен дел во поставките на складиштето:
Ги поставивме следните променливи:
SONATYPE_USERNAME / SONATYPE_PASSWORD - најава / лозинка што ја внесовме при регистрација со Sonatype
SIGNING_KEYID/SIGNING_PASSWORD — ID и лозинка на клучот PGP поставени за време на генерирањето.
Сакам подетално да се задржам на променливата GPG_KEY_CONTENTS. Факт е дека за објавување ни треба приватен PGP клуч. За да го објавам во тајните, користев настава и дополнително направи голем број на акции.
Ајде да го шифрираме нашиот клуч со gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgсо внесување лозинка. Треба да се стави во променлива: SECRET_PASSPHRASE
Ајде да го преведеме примениот шифриран клуч во текстуална форма користејќи base64: base64 9B695056.gpg.gpg > 9B695056.txt. Содржината ќе биде сместена во променливата: GPG_KEY_CONTENTS.
Изградете поставки кога туркате код и креирате ПР
Прво треба да креирате папка во коренот на вашиот проект: .github/workflows.
Во него, означете ја датотеката, на пример, gradle-ci-build.yml со следнава содржина:
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}}
Овој работен тек ќе се изврши при туркање до гранки master, dev и testing, исто така кога креирате барања за повлекување.
Делот за работни места ги одредува чекорите што треба да се извршат на наведените настани. Во овој случај, ќе ја изградиме најновата верзија на ubuntu, ќе користиме Java 8, а исто така ќе го користиме приклучокот за Gradle eskatos/gradle-command-action@v1кој, користејќи ја најновата верзија на градителот, ќе ги извршува командите наведени во arguments. Променливи secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD ова се тајните што ги прашавме претходно.
Резултатите од изградбата ќе се рефлектираат во табулаторот Дејства:
Автоматско распоредување кога ќе се објави ново издание
Ајде да создадеме посебна датотека со работниот тек за автоматско распоредување 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}}
Датотеката е речиси идентична со претходната, освен настанот во кој ќе се активира. Во овој случај, ова е настан за создавање ознака со име што започнува со v.
Пред распоредувањето, треба да го извлечеме клучот PGP од тајните и да го ставиме во коренот на проектот, како и да го дешифрираме. Следно, треба да поставиме посебна променлива на околината RELEASE_VERSION на кои се повикуваме gradle.build датотека. Сето ова е направено во делот Prepare to publish. Го добиваме нашиот клуч од променливата GPG_KEY_CONTENTS, го преведуваме во датотека gpg, а потоа го дешифрираме со ставање во датотеката secret.gpg.
Следно, се свртуваме кон посебна променлива GITHUB_REF, од која можеме да ја добиеме верзијата што ја поставивме при креирањето на ознаката. Оваа променлива е релевантна во овој случај. refs/tags/v0.0.2 од кои ги отсекувавме првите 11 знаци за да добиеме конкретна верзија. Следно, ги користиме стандардните Gradle команди за објавување: test publish
Проверка на резултатите од распоредувањето во складиштето Sonatype
Откако ќе се креира изданието, треба да започне работниот тек опишан во претходниот дел. За да го направите ова, креирајте порака:
името на ознаката мора да започнува со v. Ако, откако ќе кликнете на Објави издание, работниот тек успешно заврши, можеме да одиме до Nexus сонатип за да се уверите:
Артефактот се појави во складиштето Staging. Веднаш се појавува во статусот Отворено, потоа мора рачно да се префрли во статусот Затвори со притискање на соодветното копче. Откако ќе се провери дали се исполнети сите барања, артефактот оди во статусот Затвори и повеќе не е достапен за модификација. Во оваа форма, ќе заврши во MavenCentral. Ако сè е во ред, можете да го притиснете копчето Ослободување, а артефактот ќе заврши во складиштето на Sonatype.
За да може артефактот да влезе во MavenCentral, треба да го побарате во задачата што ја создадовме на самиот почеток. Треба да го направите ова само еднаш, затоа објавуваме за прв пат. Во следните времиња, ова не е потребно, сè ќе се синхронизира автоматски. Брзо ми вклучија синхронизација, но беа потребни околу 5 дена за артефактот да стане достапен во MavenCentral.
Тоа е сè, го објавивме нашиот артефакт во MavenCentral.