Dans cet article, je vais examiner en détail le processus de publication d'un artefact Java depuis le début via Github Actions dans le dépÎt Maven Central de Sonatype en utilisant le systÚme de build Gradle.
J'ai décidé d'écrire cet article en raison de l'absence d'un tutoriel adéquat en un seul endroit. J'ai dû recueillir toutes les informations par morceaux à partir de diverses sources, qui n'étaient pas toujours trÚs récentes. Pour ceux que cela intéresse, bienvenue sous le cut.
Création d'un dépÎt dans Sonatype
La premiĂšre Ă©tape consiste Ă crĂ©er un dĂ©pĂŽt dans Maven Central de Sonatype. Pour cela, nous allons , nous inscrire et crĂ©er une nouvelle tĂąche, avec une demande de crĂ©ation de dĂ©pĂŽt pour nous. Nous saisissons notre GroupId du projet, URL du projet un lien vers le projet et SCM url un lien vers le systĂšme de contrĂŽle de version dans lequel se trouve le projet. GroupId Ceci doit ĂȘtre sous la forme com.example, com.example.domain, com.example.testsupport, ou peut Ă©galement prendre la forme d'un lien vers votre GitHub : -> io.github.yourusername. Dans tous les cas, vous devrez confirmer la propriĂ©tĂ© de ce domaine ou de ce profil. Si vous avez indiquĂ© un profil GitHub, on vous demandera de crĂ©er un dĂ©pĂŽt public avec le nom requis.
AprÚs un certain temps, une fois la propriété confirmée, votre GroupId sera créé et nous pourrons passer à l'étape suivante, la configuration de Gradle.
Configuration de Gradle
Au moment de la rĂ©daction de cet article, je n'ai trouvĂ© aucun plugin pour Gradle qui pourrait aider Ă la publication de l'artefact. Le seul plugin que j'ai trouvĂ©, cependant, l'auteur a renoncĂ© Ă son soutien ultĂ©rieur. J'ai donc dĂ©cidĂ© de tout faire moi-mĂȘme, d'autant plus que ce n'est pas trop compliquĂ©.
La premiÚre chose à déterminer est les exigences de Sonatype pour la publication. Elles sont les suivantes :
- La présence des codes sources et de la JavaDoc, c'est-à -dire que doivent figurer
-sources.jaret-javadoc.jardes fichiers. Comme indiquĂ© dans la documentation, s'il n'est pas possible de fournir les codes sources ou la documentation, vous pouvez crĂ©er un vide-sources.jarou-javadoc.jaravec un simple README Ă l'intĂ©rieur, afin de passer la vĂ©rification. - Tous les fichiers doivent ĂȘtre signĂ©s Ă l'aide de
GPG/PGPet.ascle fichier contenant la signature doit ĂȘtre inclus pour chaque fichier. - PrĂ©sence
pomfichiers - Valeurs correctes
groupId,artifactIdetversion. La version peut ĂȘtre une chaĂźne arbitraire et ne peut pas se terminer par-SNAPSHOT - La prĂ©sence de
nom,descriptioneturl - Informations sur la licence, les développeurs et le systÚme de contrÎle de version
Ce sont les principales rĂšgles qui doivent ĂȘtre respectĂ©es lors de la publication. Des informations complĂštes sont disponibles .
Nous allons mettre en Ćuvre ces exigences dans build.gradle fichier. Pour commencer, ajoutons toutes les informations nĂ©cessaires sur les dĂ©veloppeurs, la licence, le systĂšme de contrĂŽle de versions, ainsi que dĂ©finissons l'url, le nom et la description du projet. Pour ce faire, Ă©crivons une mĂ©thode simple :
def customizePom(pom) {
pom.withXml {
def root = asNode()
root.dependencies.removeAll { dep ->
dep.scope == "test"
}
root.children().last() + {
resolveStrategy = DELEGATE_FIRST
description 'Une description de lâartefact'
name 'Nom de lâartĂ©fact'
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 'La Licence 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 'NomDuDev'
email 'email@dev.fr'
}
}
}
}
}Ensuite, il faut indiquer que des -sources.jar et-javadoc.jar fichiers doivent ĂȘtre gĂ©nĂ©rĂ©s lors de la compilation. Pour cela, dans la section java , il faut ajouter ce qui suit :
java {
withJavadocJar()
withSourcesJar()
}Passons Ă la derniĂšre exigence, la configuration de la signature GPG/PGP. Pour cela, connectons le plugin signing:
plugins {
id 'signing'
}Et ajoutons la section :
signing {
sign publishing.publications
}Enfin, ajoutons la section 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
}
}
}
}Ici sonatypeUsername et sonatypePassword variables contenant le nom d'utilisateur et le mot de passe créés lors de l'inscription sur .
Ainsi, le final build.gradle devrait ressembler Ă ceci :
Code complet 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 'Une description de l'artifact'
name 'Nom de l'artifact'
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 'La licence 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 'NomDuDev'
email 'email@dev.fr'
}
}
}
}
}Je tiens à noter que nous obtenons la version à partir de la variable d'environnement : System.getenv('RELEASE_VERSION'). Nous la définirons lors de la construction et la prendrons à partir du nom de la balise.
Génération de la clé PGP
Une des exigences de Sonatype est de signer tous les fichiers à l'aide de la clé GPG/PGP. Pour cela, allons et téléchargeons l'utilitaire GnuPG pour notre systÚme d'exploitation.
- Générons une paire de clés :
gpg --gen-key, saisissons le nom d'utilisateur, l'e-mail, et définissons également un mot de passe. - Nous découvrons
idnotre clé avec la commande :gpg --list-secret-keys --keyid-format short. L'ID sera indiqué aprÚs la barre, par exemple : rsa2048/9B695056 - Publions la clé publique sur le serveur avec la commande :
gpg --keyserver [https://keys.openpgp.org](https://keys.openpgp.org/) --send-keys 9B695056 - Exportons la clé secrÚte à un emplacement arbitraire, nous en aurons besoin par la suite :
gpg --export-secret-key 9B695056 > D:\gpg\9B695056.gpg
Configurer Github Actions
Passons à l'étape finale, configurons la compilation et la publication automatique en utilisant Github Actions.
Github Actions est une fonctionnalitĂ© qui permet d'automatiser le flux de travail, en rĂ©alisant un cycle CI/CD complet. La compilation, les tests et le dĂ©ploiement peuvent ĂȘtre dĂ©clenchĂ©s par divers Ă©vĂ©nements : un push de code, la crĂ©ation d'une release ou d'issues. Cette fonctionnalitĂ© est totalement gratuite pour les dĂ©pĂŽts publics.
Dans cette section, je vais montrer comment configurer la compilation et le push du code ainsi que le déploiement dans le dépÎt Sonatype lors de la sortie d'une release, ainsi que la configuration des secrets.
Configuration des secrets
Pour une compilation et un dĂ©ploiement automatiques, nous aurons besoin d'une sĂ©rie de valeurs secrĂštes, telles que l'ID de clĂ©, le mot de passe que nous avons saisi lors de la gĂ©nĂ©ration de la clĂ©, la clĂ© PGP elle-mĂȘme ainsi que le login/mot de passe pour Sonatype. Ils peuvent ĂȘtre dĂ©finis dans une section spĂ©ciale des paramĂštres du dĂ©pĂŽt :

Nous définissons les variables suivantes :
- SONATYPE_USERNAME/SONATYPE_PASSWORD â login/mot de passe que nous avons saisi lors de l'inscription sur Sonatype
- SIGNING_KEYID/SIGNING_PASSWORD â ID de la clĂ© PGP et mot de passe dĂ©fini lors de la gĂ©nĂ©ration.
Je veux m'attarder un peu plus sur la variable GPG_KEY_CONTENTS. En effet, pour publier, nous avons besoin de la clé PGP privée. Pour l'intégrer dans les secrets, j'ai suivi l' et j'ai également effectué plusieurs actions supplémentaires.
- Chiffrons notre clé avec gpg :
gpg --symmetric --cipher-algo AES256 9B695056.gpg, en saisissant le mot de passe. Celui-ci doit ĂȘtre placĂ© dans la variable : SECRET_PASSPHRASE - Convertissons la clĂ© chiffrĂ©e obtenue en forme texte avec base64 :
base64 9B695056.gpg.gpg > 9B695056.txt. Le contenu sera placé dans la variable : GPG_KEY_CONTENTS.
Configuration de la compilation lors du push de code et de la création d'un PR
Tout d'abord, créez un dossier à la racine de votre projet : .github/workflows.
Dans celui-ci, placez un fichier, par exemple, gradle-ci-build.yml avec le contenu suivant :
name: build
on:
push:
branches:
- master
- dev
- testing
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Configurer JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Construire avec Gradle
uses: eskatos/gradle-command-action@v1
with:
gradle-version: current
arguments: build -PsonatypeUsername=${{secrets.SONATYPE_USERNAME}} -PsonatypePassword=${{secrets.SONATYPE_PASSWORD}}Ce workflow sera exécuté lors d'un push dans les branches master, dev et testing, ainsi que lors de la création de pull requests.
Dans la section jobs, les Ă©tapes qui doivent ĂȘtre rĂ©alisĂ©es selon les Ă©vĂ©nements spĂ©cifiĂ©s sont indiquĂ©es. Dans ce cas, nous construirons sur la derniĂšre version d'ubuntu, utiliserons Java 8, ainsi qu'un plugin pour Gradle. eskatos/gradle-command-action@v1, qui, en utilisant la derniĂšre version de l'assembleur, exĂ©cutera les commandes spĂ©cifiĂ©es dans arguments. Variables secrets.SONATYPE_USERNAME et secrets.SONATYPE_PASSWORD ce sont des secrets que nous avons dĂ©finis prĂ©cĂ©demment.
Les résultats de la construction seront reflétés dans l'onglet Actions :

Déploiement automatique à la publication d'une nouvelle version
Pour le déploiement automatique, nous allons créer un fichier de workflow séparé gradle-ci-publish.yml:
name: publish
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Configurer JDK 8
uses: actions/setup-java@v1
with:
java-version: 8
- name: Préparer à publier
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: Publier avec 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}}Le fichier est pratiquement identique au précédent, à l'exception de l'événement qui va le déclencher. Dans ce cas, il s'agit de l'événement de création d'une balise dont le nom commence par v.
Avant le déploiement, nous devons extraire la clé PGP des secrets et la placer à la racine du projet, ainsi que la déchiffrer. Ensuite, nous devons définir une variable d'environnement spéciale RELEASE_VERSION à laquelle nous faisons référence dans gradle.build fichier. Tout cela est fait dans la section Préparer à publier. Nous récupérons notre clé à partir de la variable GPG_KEY_CONTENTS, convertissons-la en fichier gpg, puis la déchiffrons et la plaçons dans le fichier secret.gpg.
Ensuite, nous accédons à une variable spéciale GITHUB_REF, à partir de laquelle nous pouvons extraire la version que nous avons définie lors de la création de la balise. Cette variable a dans ce cas la valeur refs/tags/v0.0.2 de laquelle nous coupons les 11 premiers caractÚres pour obtenir la version exacte. Ensuite, nous utilisons normalement les commandes Gradle pour la publication : test publish
Vérification des résultats du déploiement dans le référentiel Sonatype
AprÚs la création de la version, le workflow décrit dans la section précédente doit se déclencher. Pour ce faire, nous créons une version :

oĂč le nom de la balise doit commencer par v. Lorsque vous appuyez sur Publier la version, si le workflow s'exĂ©cute avec succĂšs, nous pouvons nous rendre sur pour vĂ©rifier cela :

L'artefact est apparu dans le dĂ©pĂŽt Staging. Il apparaĂźt immĂ©diatement dans le statut Ouvert, puis il doit ĂȘtre manuellement transfĂ©rĂ© au statut Clos en appuyant sur le bouton correspondant. AprĂšs vĂ©rification du respect de toutes les exigences, l'artefact passe au statut Clos et n'est plus disponible pour modification. Sous cette forme, il sera intĂ©grĂ© dans MavenCentral. Si tout est en ordre, vous pouvez appuyer sur le bouton Publication, l'artefact sera alors transfĂ©rĂ© dans le dĂ©pĂŽt Sonatype.
Pour que l'artefact atteigne MavenCentral, il est nĂ©cessaire d'en faire la demande dans la tĂąche que nous avons créée au tout dĂ©but. Cela doit ĂȘtre fait uniquement une fois, car c'est la premiĂšre publication. Pour les fois suivantes, cela n'est pas nĂ©cessaire, tout sera synchronisĂ© automatiquement. J'ai reçu la synchronisation rapidement, mais il a fallu environ 5 jours pour que l'artefact devienne disponible dans MavenCentral.
C'est tout, nous avons publié notre artefact dans MavenCentral.
Liens utiles
- Semblable , seulement la publication se fait par maven
- Staging Sonatype
- Sonatype, oĂč il est nĂ©cessaire de crĂ©er une tĂąche
- dĂ©pĂŽt oĂč tout cela est configurĂ©
Source : habr.com
