ProHoster > Blog > Administración > Usando accións Gradle e Github para publicar o proxecto Java no repositorio central de Sonatype Maven
Usando accións Gradle e Github para publicar o proxecto Java no repositorio central de Sonatype Maven
Neste artigo, quero botar unha ollada máis de cerca ao proceso de publicación dun artefacto Java desde cero a través de Github Actions para o repositorio central de Sonatype Maven usando o constructor Gradle.
Decidín escribir este artigo debido á falta dun titorial normal nun só lugar. Toda a información tiña que ser recollida peza a peza de diversas fontes, ademais, non totalmente fresca. Quen lle importa, benvido baixo gato.
Creando un repositorio en Sonatype
O primeiro paso é crear un repositorio en Sonatype Maven Central. Para iso imos aquí, rexistrarse e crear unha nova tarefa, solicitándonos que creemos un repositorio. Conducimos no noso GroupId proxecto, URL do proxecto ligazón do proxecto e URL SCM unha ligazón ao sistema de control de versións no que se atopa o proxecto. GroupId aquí debería ter o formato com.example, com.example.domain, com.example.testsupport e tamén pode ter a forma dunha ligazón ao teu github: github.com/yourusername -> io.github.yourusername. En calquera caso, terás que verificar a propiedade deste dominio ou perfil. Se especificaches un perfil github, pediráselle que crees un repositorio público co nome desexado.
Algún tempo despois da confirmación, crearase o teu GroupId e poderemos pasar ao seguinte paso, a configuración de Gradle.
Configurando Gradle
No momento de escribir este artigo, non atopei complementos de Gradle que puidesen axudar a publicar o artefacto. El o único complemento que atopei, con todo, o autor negouse a apoialo. Polo tanto, decidín facer todo eu, xa que non é moi difícil facelo.
O primeiro que hai que descubrir son os requisitos de Sonatype para publicar. Son os seguintes:
Dispoñibilidade de códigos fonte e JavaDoc, é dicir. debe asistir -sources.jar и-javadoc.jar arquivos. Como se indica na documentación, se non é posible proporcionar códigos fonte ou documentación, podes facer un simulacro -sources.jar ou -javadoc.jar cun sinxelo README dentro para pasar a proba.
Todos os ficheiros deben estar asinados con GPG/PGPE .asc para cada expediente deberá incluírse o ficheiro que conteña a sinatura.
dispoñibilidade pom arquivo
Valores correctos groupId, artifactId и version. A versión pode ser unha cadea arbitraria e non pode rematar con -SNAPSHOT
Requírese presenza name, description и url
A presenza de información sobre a licenza, os desenvolvedores e o sistema de control de versións
Estas son as normas básicas que se deben seguir á hora de publicar. Información completa dispoñible aquí.
Implementamos estes requisitos en build.gradle arquivo. En primeiro lugar, imos engadir toda a información necesaria sobre os desenvolvedores, licenzas, sistema de control de versións, e tamén establecer o URL, nome e descrición do proxecto. Escribamos un método sinxelo para iso:
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]'
}
}
}
}
}
A continuación, cómpre especificalo durante a montaxe xerada -sources.jar и-javadoc.jar arquivos. Para esta sección java cómpre engadir o seguinte:
java {
withJavadocJar()
withSourcesJar()
}
Pasemos ao último requisito, configurar unha sinatura GPG/PGP. Para iso, conecte o complemento signing:
plugins {
id 'signing'
}
E engade unha sección:
signing {
sign publishing.publications
}
Finalmente, imos engadir unha sección 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
}
}
}
}
Aquí sonatypeNome de usuario и sonatypePassword variables que conteñen o inicio de sesión e o contrasinal creados durante o rexistro sonatype.org.
Así a final build.gradle quedará así:
Código completo 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]'
}
}
}
}
}
Quero notar que obtemos a versión da variable de ambiente: System.getenv('RELEASE_VERSION'). Expoñerémolo durante a montaxe e tomarémolo do nome da etiqueta.
Xeración de claves PGP
Un dos requisitos de Sonatype é que todos os ficheiros estean asinados cunha clave GPG/PGP. Para iso imos aquí e descarga a utilidade GnuPG para o teu sistema operativo.
Xeramos un par de claves: gpg --gen-key, introduza un nome de usuario, un correo electrónico e tamén configure un contrasinal.
Descubrindo id nosa chave co comando: gpg --list-secret-keys --keyid-format short. O ID especificarase despois da barra, por exemplo: rsa2048/9B695056
Publicación da chave pública no servidor https://keys.openpgp.org comando: gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056
Exportamos a clave secreta a un lugar arbitrario, necesitarémola no futuro: gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Configurando accións de Github
Pasemos á fase final, configure a compilación e a publicación automática usando Github Actions.
Github Actions é unha función que che permite automatizar o fluxo de traballo implementando un ciclo completo de CI/CD. A creación, proba e implantación pódense activar por varios eventos: push de código, creación de versións ou problemas. Esta funcionalidade é absolutamente gratuíta para os repositorios públicos.
Nesta sección, mostrarei como configurar código de compilación e inserción e implementación no repositorio de Sonatype na súa publicación, así como configurar segredos.
Establecemos segredos
Para a montaxe e o despregamento automáticos, necesitamos unha serie de valores secretos, como o ID da chave, o contrasinal que introducimos ao xerar a chave, a propia chave PGP e o inicio de sesión/contrasinal de Sonatype. Podes configuralos nunha sección especial na configuración do repositorio:
Establecemos as seguintes variables:
SONATYPE_USERNAME / SONATYPE_PASSWORD - inicio de sesión / contrasinal que introducimos ao rexistrarse con Sonatype
SIGNING_KEYID/SIGNING_PASSWORD — ID da chave PGP e contrasinal definidos durante a xeración.
Quero determe na variable GPG_KEY_CONTENTS con máis detalle. O caso é que para a publicación necesitamos unha clave PGP privada. Para publicalo nos segredos, usei instrución e, ademais, realizou unha serie de accións.
Imos cifrar a nosa chave con gpg: gpg --symmetric --cipher-algo AES256 9B695056.gpgintroducindo un contrasinal. Debe colocarse nunha variable: SECRET_PASSPHRASE
Imos traducir a clave cifrada recibida nun formulario de texto usando base64: base64 9B695056.gpg.gpg > 9B695056.txt. O contido colocarase na variable: GPG_KEY_CONTENTS.
Construír a configuración ao presionar código e crear PR
Primeiro tes que crear un cartafol na raíz do teu proxecto: .github/workflows.
Nel, marca o ficheiro, por exemplo, gradle-ci-build.yml co seguinte contido:
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}}
Este fluxo de traballo executarase ao empurrar a ramas master, dev и testing, tamén ao crear solicitudes de extracción.
A sección de traballos especifica os pasos a executar nos eventos especificados. Neste caso, construiremos a última versión de ubuntu, usaremos Java 8 e tamén usaremos o complemento para Gradle eskatos/gradle-command-action@v1que, usando a versión máis recente do constructor, executará os comandos especificados en arguments. Variables secrets.SONATYPE_USERNAME и secrets.SONATYPE_PASSWORD estes son os segredos que preguntamos anteriormente.
Os resultados da compilación reflectiranse na pestana Accións:
Implementación automática cando se lanza unha nova versión
Imos crear un ficheiro de fluxo de traballo separado para a implementación automática 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}}
O ficheiro é case idéntico ao anterior, agás o evento no que se desencadeará. Neste caso, este é o evento de crear unha etiqueta cun nome que comeza por v.
Antes da implantación, necesitamos extraer a clave PGP dos segredos e colocala na raíz do proxecto, así como descifrala. A continuación, necesitamos establecer unha variable de ambiente especial RELEASE_VERSION ao que nos referimos gradle.build arquivo. Todo isto faise na sección Prepare to publish. Obtemos a nosa clave da variable GPG_KEY_CONTENTS, traducímola a un ficheiro gpg e despois desciframos poñéndoa no ficheiro secret.gpg.
A continuación, pasamos a unha variable especial GITHUB_REF, da que podemos obter a versión que establecemos ao crear a etiqueta. Esta variable é relevante neste caso. refs/tags/v0.0.2 do que cortamos os primeiros 11 caracteres para obter unha versión específica. A continuación, usamos os comandos estándar de Gradle para publicar: test publish
Comprobando os resultados da implantación no repositorio de Sonatype
Unha vez creada a versión, debería comezar o fluxo de traballo descrito na sección anterior. Para iso, crea unha versión:
o nome da etiqueta debe comezar por v. Se despois de facer clic en Publicar versión, o fluxo de traballo remata con éxito, podemos ir a Sonatype Nexus para asegurarse:
O artefacto apareceu no repositorio de Staging. Aparece inmediatamente no estado Aberto, entón debe transferirse manualmente ao estado Pechar premendo o botón correspondente. Despois de comprobar que se cumpren todos os requisitos, o artefacto pasa ao estado Pechar e xa non está dispoñible para a súa modificación. Deste xeito, rematará en MavenCentral. Se todo está ben, podes premer o botón Solte, e o artefacto acabará no repositorio de Sonatype.
Para que o artefacto entre en MavenCentral, debes solicitalo na tarefa que creamos ao principio. Só tes que facelo unha vez, polo que publicamos por primeira vez. En tempos posteriores, isto non é necesario, todo sincronizarase automaticamente. Activaron a sincronización para min rapidamente, pero o artefacto tardou uns 5 días en estar dispoñible en MavenCentral.
Iso é todo, publicamos o noso artefacto en MavenCentral.