Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Déployer un fichier aar sur Maven Central avec Gradle

2 janvier 2015

Il y a bientôt un an, dans le cadre d’un projet Android, j’ai été amené à utiliser et modifier ce carousel 3D. Cela faisait un petit moment que je souhaitais mettre à disposition des développeurs mes modifications, c’est chose faite sur Github. Afin de faciliter l’intégration de ce widget, j’ai souhaité le mettre à disposition de tous en le déposant sur Maven Central.

Déposer un fichier aar sur Maven Central n’est pas évident. C’est pourquoi je vous propose dans cet article de revenir sur les différentes étapes de ce processus.

Étape 1 : création d’un compte Sonatype

La première des six étapes consiste à créer un compte sur le JIRA Sonatype.

Pour ceux qui ignorent ce qu’est JIRA, voici la définition que donne Wikipedia :

Si vous ne connaissez pas ce logiciel je vous invite à aller visiter leur site : fr.atlassian.com.

Une fois sur la page de création de compte, vous devez donc remplir le formulaire suivant et le valider en cliquant sur le bouton Sign up :

Étape 2 : création d’un ticket

Maintenant que vous êtes inscrit et connecté à JIRA, il convient de créer un nouveau ticket JIRA dans lequel vous devez renseigner les informations relatives à la bibliothèque que vous souhaitez mettre à disposition des développeurs.

Pour créer un nouveau ticket, vous avez la possibilité de passer via les menus de JIRA ou de cliquer directement ici. Vous devriez alors avoir le formulaire suivant sous les yeux :

Une fois le formulaire saisi, cliquez sur le bouton Create pour le valider. Une fois le formulaire validé, il convient d’attendre qu’un administrateur valide votre projet et vous confirme que vous pouvez le déployer. Cette opération de validation peut prendre jusqu’à deux jours. Dans mon cas, elle n’a pris que quelques minutes.

Étape 3 : le script de déployement Gradle

Le script maven.gradle

Comme le suggère le titre de l’article, nous allons utiliser Gradle pour déployer notre fichier aar sur Maven Central. Il convient donc de mettre en place un script permettant de créer l’archive Android, la signer et la déployer.

Ecrire ce script soit même est assez long et d’autres l’ont fait pour nous. Aussi, je vous encourage à en utiliser un disponible par exemple sur Github Gist.

Voici son contenu :

/*
 * Copyright 2013 Chris Banes
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

apply plugin: 'maven'
apply plugin: 'signing'

def isReleaseBuild() {
    return VERSION_NAME.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
    return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
            : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}

def getSnapshotRepositoryUrl() {
    return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
            : "https://oss.sonatype.org/content/repositories/snapshots/"
}

def getRepositoryUsername() {
    return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}

def getRepositoryPassword() {
    return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}

afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

                pom.groupId = GROUP
                pom.artifactId = POM_ARTIFACT_ID
                pom.version = VERSION_NAME

                repository(url: getReleaseRepositoryUrl()) {
                    authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
                }
                snapshotRepository(url: getSnapshotRepositoryUrl()) {
                    authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
                }

                pom.project {
                    name POM_NAME
                    packaging POM_PACKAGING
                    description POM_DESCRIPTION
                    url POM_URL

                    scm {
                        url POM_SCM_URL
                        connection POM_SCM_CONNECTION
                        developerConnection POM_SCM_DEV_CONNECTION
                    }

                    licenses {
                        license {
                            name POM_LICENCE_NAME
                            url POM_LICENCE_URL
                            distribution POM_LICENCE_DIST
                        }
                    }

                    developers {
                        developer {
                            id POM_DEVELOPER_ID
                            name POM_DEVELOPER_NAME
                        }
                    }
                }
            }
        }
    }

    signing {
        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
        sign configurations.archives
    }

    //task androidJavadocs(type: Javadoc) {
        //source = android.sourceSets.main.allJava
    //}

    //task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
        //classifier = 'javadoc'
        //from androidJavadocs.destinationDir
    //}

    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.sourceFiles
    }

    artifacts {
        archives androidSourcesJar
    }
}

Enregistrez le fichier sous le nom maven.gradle au même niveau que le fichier build.gradle de votre bibliothèque puis ajoutez dans le fichier build.gradle une référence vers le fichier à l’aide de la ligne suivante :

apply from: 'maven.gradle'

Le fichier gradle.properties

Au même niveau que les fichiers maven.gradle et build.gradle de votre bibliothèque, créez le fichier gradle.properties. Ce fichier va nous permettre d’alimenter le script maven.gradle avec les informations relatives à notre projet. Voici son squelette :

POM_NAME=
POM_ARTIFACT_ID=
POM_PACKAGING=
VERSION_NAME=
VERSION_CODE=
GROUP=

POM_DESCRIPTION=
POM_URL=
POM_SCM_URL=
POM_SCM_CONNECTION=scm:hg:
POM_SCM_DEV_CONNECTION=scm:hg:
POM_LICENCE_NAME=
POM_LICENCE_URL=
POM_LICENCE_DIST=
POM_DEVELOPER_ID=
POM_DEVELOPER_NAME=

NEXUS_USERNAME=
NEXUS_PASSWORD=

SNAPSHOT_REPOSITORY_URL=
RELEASE_REPOSITORY_URL=

signing.keyId=
signing.password=
signing.secretKeyRingFile=

Voici par exemple le contenu de celui utilisé pour mon carousel Android :

POM_NAME=Android 3D Carousel
POM_ARTIFACT_ID=carousel
POM_PACKAGING=aar
VERSION_NAME=1.0.0
VERSION_CODE=1
GROUP=fr.rolandl

POM_DESCRIPTION=An Android 3D Carousel based on http://www.codeproject.com/Articles/146145/Android-D-Carousel
POM_URL=https://github.com/ludovicroland/carousel-android
POM_SCM_URL=https://github.com/ludovicroland/carousel-android
POM_SCM_CONNECTION=scm:hg:https://github.com/ludovicroland/carousel-android
POM_SCM_DEV_CONNECTION=scm:hg:https://github.com/ludovicroland/carousel-android
POM_LICENCE_NAME=The Code Project Open License (CPOL) 1.02
POM_LICENCE_URL=http://www.codeproject.com/info/cpol10.aspx
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=rolandl
POM_DEVELOPER_NAME=Ludovic ROLAND

NEXUS_USERNAME=Votre_Login_JIRA
NEXUS_PASSWORD=Votre_Mot_de_passe_JIRA

SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots
RELEASE_REPOSITORY_URL=https://oss.sonatype.org/service/local/staging/deploy/maven2

signing.keyId=Votre_keyId
signing.password=Votre_key_password
signing.secretKeyRingFile=C:/Users/Ludovic ROLAND/AppData/Roaming/gnupg/secring.gpg

A ce stade, les seules informations que vous n’êtes pas en mesure de renseigner sont les 3 dernières, à savoir :

  • signing.keyId
  • signing.password
  • signing.secretKeyRingFile

Ces champs sont ceux qui vont nous permettre de signer notre bibliothèque. Pour les renseigner, il convient de créer une clef GPG. Il s’agit de la prochaine étape. ;)

Étape 4 : les clefs GPG

Installation des outils

Pour pouvoir signer la bibliothèque à déployer, il convient d’utiliser une clef GPG. Si vous êtes sous Linux ou sous Max OS X, tous les outils nécessaires à cette quatrième étape sont déjà installés sur votre machine. Si vous êtes sous Windows, il convient d’installer le logiciel Gpg4win, disponible gratuitement ici.

Une fois le logiciel installé, ouvrez un terminal ou une invite de commandes suivant votre système d’exploitation.

Génération des clefs GPG

Pour générer les clefs GPG, il convient de saisir la commande suivante :

gpg --gen-key

Vous devriez alors être amené à renseigner les informations suivantes :

  1. le type de la clef ;
  2. la taille de la clef ;
  3. le temps de validité de la clef ;
  4. l’identité de la clef ;
  5. une phrase de protection de la clef.

Pour les étapes 1 à 3, vous pouvez utiliser les valeurs par défaut à savoir :

  • RSA et RSA pour le type ;
  • 2048 pour la taille ;
  • la clef n’expire pas pour le temps de validité.

Pour l’identité, il convient de saisir votre nom réel (prénom + nom) et votre adresse e-mail.

Voici un exemple d’exécution du script sous Windows :

Au moment de saisir la phrase de protection de la clef, vous devriez voir une boite de dialogue s’ouvrir :

Une fois la génération des clefs terminée, nous allons pouvoir récupérer les informations qui nous intéressent pour compléter notre fichier gradle.properties.

Récupération des informations de la clef privée GPG

Pour récupérer les informations destinées à alimenter les champs signing.keyId, signing.password et signing.secretKeyRingFile du fichier gradle.properties, il convient de saisir la commande suivante :

gpg --list-secret-keys

Vous devriez alors avoir les informations suivantes s’afficher à l’écran :

Vous êtes maintenant capable de renseigner les différents champs :

  • Pour le champ signing.keyId utilisez ce que j’ai entouré en vert.
  • Pour le champ signing.password utilisez la phrase de protection que vous avez saisi.
  • Pour le champ signing.secretKeyRingFile utilisez ce que j’ai entouré en rouge.

Publier les clefs GPG

Il convient maintenant de publier vos clefs grâce à la ligne de commande suivante :

gpg --keyserver hkp://pgp.mit.edu --send-keys keyId

KeyId est à remplacer par votre propre keyId, c’est-à-dire par ce que j’ai entouré en vert dans la précédente capture d’écran.

Voici ce à quoi ça ressemble sous Windows :

Étape 5 : déploiement du fichier aar

Nous allons maintenant envoyer notre fichier aar sur Maven Central. Pour ce faire, il convient simplement de saisir la commande gradle suivante :

gradle uploadArchives

Vous devriez alors voir votre script travailler et être notifié d’un BUILD SUCCESSFUL si tout se passe bien :

Étape 6 : publication de la bibliothèque

Maintenant que votre bibliothèque a été poussé sur Maven Central, il convient de la publier afin qu’elle soit accessible et utilisable de tous.

Pour se faire, rendez-vous ici. Identifiez-vous et repérez dans la liste le dépôt qui correspond à votre bibliothèque comme dans la capture d’écran ci-dessous :

Cochez la ligne puis cliquez sur Close :

Vous devriez alors voir l’icône de votre dépôt changer, signe qu’une opération est en cours :

Une fois l’opération terminée, si tout s’est bien passé, vous devriez être en mesure de cliquer sur le bouton Release :

Une fois l’opération terminée, il ne vous reste plus qu’à retourner sur votre ticket JIRA pour y ajouter un commentaire comme quoi vous venez de publier votre bibliothèque.

Votre bibliothèque sera ensuite accessible à tous au bout de quelques minutes.

Commentaires