Tuesday, November 15, 2022

Android aar deployment in Maven - 2022

Introduction

If you are working on android library project, you might be wondering how to publish it on Maven like this. Earlier it was done using Android studio plugin maven, but with gradle v 7.0+ it does not work. Now we have to use maven-publish. This post gives you more insights of this procedure.

Generally, there are two types of repositories: local and remote.

A local repository is the repository Maven creates on the computer it is building on. It is usually located under the $HOME/.m2/repository directory.

ls -l ~/.m2/repository/com/swapnilutilities/swapnilCalculator/0.0.1
swapnilCalculator-0.0.1-javadoc.jar swapnilCalculator-0.0.1-sources.jar swapnilCalculator-0.0.1.aar swapnilCalculator-0.0.1.module swapnilCalculator-0.0.1.pom

Remote repository is located on maven server. When any user wants to use our library, they will enter groupId and version of library they want to use.
We will create and deploy a new android aar artifact on maven.
The process can be summarized as
1. Create Account and repository on Nexus sonatype
2. Configure gradle to create, sign and upload aar file to sonatype.
3. Let sonatype verify the artifacts as per maven requirement (Close operation)
4. Release artifacts to maven.

Let's go through the steps one by one.

1. Create account on sonatype at https://issues.sonatype.org/secure/Dashboard.jspa. Register new project by creating new jira ticket. It will create new repository in sonatype
Create → Create Issue → Community Support - Open Source Project Repository Hosting → New Project → with groupid io.bitbucket.swapnilcpublic e.g. OSSRH-85813

2. You will be asked to prove that you own the domain mentioned in Jira ticket. (e.g. https://bitbucket.org/swapnilcpublic). You will be asked to place a file or create git repo under the domain to prove that it really belongs to you. Since I do not own a domain name, I created empty bitbucket repo under bitbucket repo. Here ossrh-85813 is the JIRA ticket id. For more details follow how-to-set-txt-record and personal groupId. If required a static web site can be created using bitbucket.

3. Signing: One of the requirements for publishing your artifacts to the Central Repository, is that they have been signed with PGP. Here is how tosetup signing with gpg.
Create new key with details like

Name: SwapnilGpg
Email: email@id.com
Pass: password
After creation, see created keys with
gpg --list-keys
/Users/swapnilchaudhari/.gnupg/pubring.kbx
------------------------------------------
pub rsa4096 2022-11-10 [SC] [expires: 2026-11-10]
0D879958847AD37E72FECF1
uid [ultimate] SwapnilGpg <email@id.com>
sub rsa4096 2022-11-10 [E] [expires: 2026-11-10]

Export secret keys using
gpg --keyring secring.gpg --export-secret-keys > ~/.gnupg/secring.gpg

We need short key. It will be referred from gradle script. It appears after `rsa4096/` in output. Find short KeyId using
gpg --list-keys --keyid-format SHORT
pub rsa4096/E72FECF1 2022-11-10 [SC]
80B74D9C1E696BA2C0D879958847AD37E72FECF1

Once the GPG keys are generated, publish these keys to an open key server. Run the following command to do so. YYYYYYYY is the short key generated using previous step (E72FECF1 in my case).
gpg --keyserver hkp://keyserver.ubuntu.com --send-keys YYYYYYYY
gpg --keyserver hkp://pgp.mit.edu --send-keys YYYYYYYY

Verify these keys using
gpg --keyserver hkp://pgp.mit.edu --search-keys email@id.com

4. Update build.gradle in ProjectRoot/swapnilCalculator/build.gradle with following

plugins {
...
id 'maven-publish'
id 'signing'
}
android {
...
publishing {
singleVariant('release') {
withSourcesJar()
withJavadocJar()
}
}
}
signing {
publishing.publications.all { publication ->
sign publication
}
}
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
groupId = GROUP
artifactId = POM_ARTIFACT_ID
version = VERSION_NAME
afterEvaluate {
from components.release
}
pom {
name = POM_ARTIFACT_ID
description = POM_DESCRIPTION
url = POM_URL
properties = [
versionCode: VERSION_CODE
]
licenses {
license {
name = POM_LICENCE_NAME
url = POM_LICENCE_URL
}
}
developers {
developer {
id = POM_DEVELOPER_ID
name = POM_DEVELOPER_NAME
email = POM_DEVELOPER_EMAIL
}
}
scm {
connection = POM_SCM_CONNECTION
developerConnection = POM_SCM_DEV_CONNECTION
url = POM_URL
}
}
}
}
repositories {
maven {
def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
credentials {
username NEXUS_USERNAME
password NEXUS_PASSWORD
}
authentication {
basic(BasicAuthentication)
}
}
}
}
}

5. Add details below in ProjectRoot/gradle.properties

signing.keyId=<short key of GPG>E72FECF1
signing.password=<GPG Password>
signing.secretKeyRingFile=/Users/swapnilchaudhari/.gnupg/secring.gpg
NEXUS_USERNAME=<Sonatype User ID>
NEXUS_PASSWORD=<Sonatype Password>
VERSION_NAME=0.0.2
VERSION_CODE=2
GROUP=io.bitbucket.swapnilcpublic
#POM details
POM_DESCRIPTION=Library for adding 2 integers.
POM_URL=https://swapnilcpublic.bitbucket.io/
POM_SCM_URL=https://swap_chau@bitbucket.org/swap_chau/sonatypelibraryrepo/
POM_SCM_CONNECTION=scm:git@bitbucket.com:swap_chau/sonatypelibraryrepo.git
POM_SCM_DEV_CONNECTION=scm:git@bitbucket.com:swap_chau/sonatypelibraryrepo.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=<Sonatype User ID>
POM_DEVELOPER_NAME=Swapnil Chaudhari
POM_DEVELOPER_EMAIL=email@id.com
In ProjectRoot/swapnilCalculator/gradle.properties
POM_NAME=Swapnil Calculator Library
POM_ARTIFACT_ID=swapnilCalculator
POM_PACKAGING=aar

6. Upload aar, jar and signatures using
./gradlew clean publishReleasePublicationToMavenRepository After a successful deployment to OSSRH your components are stored in a separate, temporary repository, that is private to your projects members. In order to get these components published you will have to 'close' & release' them. 'Close' operation checks whether all artifacts are as specified by Maven. 'Close' operation takes few minutes to finish. Once that is successful, proceed with 'release' operation. If there is error, please resolve them and re-upload the library.
After uploading & releasing all artifacts, it takes 4-10 hours for maven to show the library.

7. Find the published library using

  1. Sonatype staging repository
  2. Maven repository
  3. Maven repository
  4. Sonatype staging repository
  5. Sonatype nexus

8. References

  1. https://gist.github.com/lopspower/6f62fe1492726d848d6d
  2. https://central.sonatype.org/publish/
  3. https://central.sonatype.org/publish/requirements/coordinates/
  4. https://central.sonatype.org/publish/publish-guide/
  5. https://shahsurajk.medium.com/technical-publishing-aars-to-maven-central-7e9c603f9ea1
  6. https://www.baeldung.com/maven-snapshot-release-repository
  7. https://docs.gradle.org/current/userguide/signing_plugin.html#sec:signatory_credentials
  8. https://docs.gradle.org/current/userguide/publishing_maven.html

Building a Retrieval-Augmented Generation (RAG) Application with Ollama 3.2 and Spring Boot

Building a RAG Application with Ollama 3.2 and Spring Boot This blog post demonstrates how to build a Re...