8 septembre 2022 David Raluy

Publier une librairie sur le repo maven central (avec Gradle Kotlin DSL)

Hokay. Donc, vous avez fait une librairie java/kotlin, mais genre un truc vraiment chouette, pas simplement une lib qui vérifie qu’un nombre est pair ou qui retourne true. Vous vous dites que ca serait chouette de la publier sur le repo maven central, pour que tous les projets Java/Kotlin de la terre puissent en bénéficier. Malheureusement, le repo maven central a un videur devant la porte, il ne vous connaît pas, et vous n’avez pas votre carte d’identité.

Vous entrez pas

L’appel a un pote: OSSRH (OSS Repository Hosting)

Logiquement, la première chose a faire c’est d’appeler un pote qui connait le videur, et ce pote, c’est OSSRH.

En effet, le repo maven central index indexe 1700 repositories de gens de confiance. Et vous n’en faites pas partie.

OSSRH (OSS Repository Hosting), géré par Sonatype, va  se porter garant pour vous en vous permettant de créer un repository sur leur Nexus.

Vous allez ensuite uploader l’artifact sur ce repository, et OSSRH va ensuite verifier que l’artifact que vous essayer d’ajouter au repository central satisfait certaines conditions avant de l’y envoyer. Parce qu’il a envie de vous aider, mais c’est pas une bonne poire.

Premiere étape: l’inscription

Il va falloir suivre toutes les étapes décrites ici: https://central.sonatype.org/publish/publish-guide/. Elles sont assez bien décrites et largement automatisées.

La premiere sera de créer un compte sur le Jira de Sonatype: https://issues.sonatype.org, puis de créer un ticket Jira grace a ce formulaire:

Formulaire de création de repository sur OSSRH

Notez que vous devrez donner le groupId de votre artifact. Ce groupId est important a deux titres:

  • Les artifacts uploadés ultérieurement devront avoir ce même groupId
  • Il vous faudra prouver que le nom de domaine associé a ce groupId est bien en votre possession, en modifiant son DNS, (ou en créant un projet qui prouve que l’url de hosting est en votre possession)

Voici ce que le bot a répondu dans mon cas:

Un bot de Jira vous guidera en répondant au ticket de création de repository

Un bot de Jira vous guidera en répondant au ticket de création de repository

Une fois que vous avez montré patte blanche, félicitations, vous avez gagné le droit d’uploader sur s01.oss.sonatype.org!

C’est pas le repo maven central, c’est un repository maintenu par Sonatype. Une fois votre artifact uploadé et validé sur ce repository, vous pourrez le transférer sur le repo maven central.

Ce qui nous mène a l’étape suivante: la configuration du build.

Seconde étape: la configuration du build

Il ne suffit pas d’uploader un artifact. Pour que Sonatype valide votre artifact, il faudra l’accompagner de sa documentation, de ses sources, et de ses hashs. Et pour tout cela, il faudra configurer le build du projet.

La configuration du build est décrite dans la suite du guide. Elle est assez facile a suivre, bien qu’assez succincte. Néanmoins, dans mon cas, j’utilise une configuration en kotlin (Gradle Kotlin DSL), dans un fichier build.gradle.kts, pour lequel rien n’est décrit. Je vais donc vous accompagner si vous êtes dans ce cas. On est comme ça chez Arca.

Tout d’abord, il vous faudra les plugins pour publier votre jar, et le signer numériquement a l’aide d’une clé PGP (ou GPG).

Dans mon cas ça donne ça:

plugins {
    kotlin("jvm") version "1.6.21"
    `maven-publish`
    signing
}

Ensuite, le groupId utilisé précédemment, et sa version:

group = "fr.raluy.simplespreadsheet"
version = "0.0.1-SNAPSHOT"

Le fait que ce soit une version snapshot ou release a de l’importance pour la suite. Puis, on va demander de générer les sources, et la javadoc:

java {
    withJavadocJar()
    withSourcesJar()
}

Attention: l’utilisation du plugin javadoc implique des problèmes supplémentaires si votre projet utilise le systèmes de modules jigsaw apparu dans la JDK9. En effet, le code de génération de la javadoc ne connait pas les modules et dépendances du projet, et il faut les lui spécifier en plus. J’ai pour ma part décidé de m’en passer, mon stock d’aspirine arrivant à sa fin. Si vous savez le faire dans un build.gradle.kts, n’hésitez pas à lâcher un commentaire, mettre un pouce bleu et sonner la cloche.

La déclaration des repositories et des dépendances est aussi simple que d’habitude. Il s’agit des repositories qui contiennent les artifacts dont dépend votre librairie, pas ceux ou sera uploadée votre librairie.

repositories {
    mavenCentral()
}
dependencies {
    ...
}

La partie difficile est la configuration du build lors de la publication de l’artifact. Pour cela on va se raccrocher à l’extension de publication que l’on a ajoutée précédemment. Voila le gros block, n’ayez pas peur, je vous l’explique par la suite.

publishing {

    publications {
        create<MavenPublication>("mavenJava") {
            signing {
                sign(configurations.archives.get())
                sign(publishing.publications["mavenJava"])
            }
            from(components["java"])
            pom {
                name.set("Simple Spreadsheet")
                packaging = "jar"

                description.set("A simple spreasdheet parser.")
                url.set("https://github.com/Draluy/SimpleSpreadsheet")
                licenses {
                    license {
                        name.set("GNU General Public License, version 2")
                        url.set("https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html")
                    }
                }
                developers {
                    developer {
                        id.set("draluy")
                        name.set("David Raluy")
                        email.set("[email protected]")
                    }
                }
                scm {
                    connection.set("[email protected]:Draluy/SimpleSpreadsheet.git")
                    developerConnection.set("[email protected]:Draluy/SimpleSpreadsheet.git")
                    url.set("https://github.com/Draluy/SimpleSpreadsheet")
                }
            }
        }
    }

    repositories {
        maven {
            name = "myRepo"
            val releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
            val snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
            url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
            val ossrhUsername: String by project
            val ossrhPassword: String by project

            credentials {
                username = ossrhUsername
                password = ossrhPassword
            }
        }
    }

}


On va commencer par signer l’artifact. Cela se fait de manière transparente a l’aide des propriétés gradle suivantes:

signing.keyId=YourKeyId
signing.password=YourPublicKeyPassword
signing.secretKeyRingFile=PathToYourKeyRingFile

Pour générer ces informations, vous pouvez suivre ce tutoriel: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key

Problème: gpg va mettre les cles dans un nouveau format, dans un fichier .kbx. Or, le chemin attendu par secretKeyRingFile est le chemin vers un fichier secring.gpg, contenant la clé dans l’ancien format.

Pas de problème! La commande suivante vous donnera le fichier attendu: gpg –export-secret-keys -o secring.gpg

Autre problème: la documentation n’explique pas ce qu’est le keyId. Après tout, vous avez juste renseigné un identifiant et un mot de passe pour générer votre clef gpg.

Pas de problème! Commencez par lister vos clef gp avec la commande suivante:  gpg –list-secret-keys
Dans mon cas cela affiche une entrée que voici:

sec   rsa3072 2022-07-26 [SC] 
      962E62B8473F511BB9920633E9011E025D0C321A 
uid           [ultimate] David Raluy <[email protected]> 
ssb   rsa3072 2022-07-26 [E]

Le keyId sera les 8 derniers caractères de l’identifiant de la clef, a savoir dans mon cas 5D0C321A.

Ouf, voilà gpg presque dompté. Dans mon cas, il m’a fallu de plus renseigner ma clef publique gpg sur https://keyserver.ubuntu.com/ (je suis sur Ubuntu). Pour cela , il faut executer cette commande avec l’id de la clef: gpg –output pubkey.txt –armor –export [email protected]

Cela va créer un fichier pubkey.txt, contenant la clé en base64. Vous pouvez voir la mienne ici: https://keyserver.ubuntu.com/pks/lookup?search=david%40raluy.fr&fingerprint=on&op=index.

Ensuite, la configuration du pom. Ces informations sont celles qui apparaîtront dans les moteurs de recherche, comme search.maven.org. Voici un exemple: https://search.maven.org/artifact/fr.raluy.simplespreadsheet/SimpleSpreadsheet/0.0.1/jar

Enfin, la configuration de l’upload de l’artifact. J’ai fait le choix de renseigner les deux urls des repos de release et de snapshot, et de changer de l’une a l’autre en fonction du format du numéro de version. Attention: seules les versions dites de release créeront un repository vous permettant par la suite d’envoyer votre artifact sur le repo maven central. Il vous faudra de plus renseigner les propriétés gradle suivantes pour avoir le droit d’entrer:

ossrhUsername=your-jira-id
ossrhPassword=your-jira-password

Ce sont les login/mot de passe que vous avez créés précédemment lors de votre inscription a OSSRH. Vous pouvez retrouver le fichier complet de build pour mon projet d’exemple ici: https://github.com/Draluy/SimpleSpreadsheet/blob/master/build.gradle.kts

On a fini?

 

 

Troisième étape: la validation de l’artifact et l’envoi vers le repo central

On a presque fini. Si tout est bien configuré, que vous avez lancé la commande « gradle publish », et que vous publiez une version de release, vous devriez voir apparaître dans https://s01.oss.sonatype.org votre nouveau repository:

Liste de vos respoitories sur OSSRH

Il est a l’essai. Sonatype ne sait pas encore si il a le droit d’entrer dans la boîte ou pas. Pour se décider, il va lui faire passer quelques tests, que vous pourrez déclencher en cliquant sur le bouton « Close ». Cela signifie que plus rien ne sera modifiable et que vous avez fini de toute vérifier de votre côté.

Vous pourrez voir son évaluation dans la partie « Activity »:

Liste des vérifications de ossrh

Papers Please!

Si tout est OK, alors vous aurez le droit de l’envoyer vers le repo maven central en cliquant sur « Release ». Il vous faudra compter quelques heures avant qu’il n’apparaisse sur https://search.maven.org, mais il sera dispo pour la compilation au bout de 30 minutes environ. Mvnrepository.com, lui, met plus longtemps; j’y ai vu ma lib n’être indexée que le jour d’après.

En attente avant le repo maven central

Il faudra s’armer de patience

Conclusion

Et voilà, vous êtes entré après avoir été longuement scruté par le videur. En espérant qu’il se rappelle de vous la prochaine fois. Et vous ne  repartez pas sans rien: vous aurez la classe a Dallas en partageant vos releases, et puis, vous pourrez incruster votre code dans n’importe projet professionnel, parce que, bon, entre nous, personne ne veto la liste des dépendances des projets; tout le monde part du principe que si c’est sur le repo maven central, c’est du sérieux. Shhhh, je vous ai rien dit.