Ankit Kumar
6 min readFeb 9, 2024

--

Automate Android Library Publication to Maven Central via Github Actions

In this article, we’ll explore the process of publishing an Android library to Maven Central using both local command-line tools and GitHub Actions.

By following these steps, you’ll set up a seamless workflow where each GitHub release triggers the automatic publication of your library to Maven Central, ensuring that your latest updates are readily available to the wider developer community.

You can find the complete source code here : github.com

Steps to Publish Android Libraries

  1. Register Group ID on Maven by raising a Jira Ticket
  2. Generate GPG Keys | OSS_SIGNING_KEY_ID
  3. Get staging profile Id | OSS_STAGING_PROFILE_ID
  4. Generating base64 file for gpg key | OSS_SIGNING_KEY
  5. Configure root level build.gradle of project
  6. Create publish-package.gradle
  7. Configure the build.gradle file of each module
  8. Setting up environment variables
  9. Publish to Local Maven
  10. Publish SNAPSHOT to Maven
  11. Publish the Final Release to Maven
  12. Automating release via Github Action
  13. Wohoo! You just published your library 🚀

Register Group ID on Maven by raising a Jira Ticket

  • Go to Maven Jira issues and login/register.
  • Click on create button from header menu and fill the required details 👇
Project - Open Source Project Hosting
Issue Type - New Project
Summary - Create repository for io.github.pseudoankit:coachmark
Description - A light weight compose library to create onboaring experience
Group id - io.github.pseudoankit (unique identifier)
Project URL - https://github.com/pseudoankit/coachmark (github repo url)
SCM URL - https://github.com/pseudoankit/coachmark.git (github repo -> code -> copy url in https section)
Already Synced to Central - No
  • Click on create, You will recieve a email to prove your identity (just follow whatever asked, Generally they ask to create a github repo)
  • Once your request is approved, your group ID is registered which can be used in your Android project.

Your username and password will be `OSS_USERNAME` and OSS_PASSWORD respectively at later stage.

Generate GPG Keys | OSS_SIGNING_KEY_ID

GPG Keys are used to sign final artifacts before publishing them to Maven. To create a new GPG Key, run the following command and follow the instructions:

Note : -When creating you will set a password that will be `OSS_SIGNING_PASSWORD` at later stage

gpg --gen-key

After that, get the short format of GPG Key, which will be required in the next step:

gpg --list-keys --keyid-format short

The output may look like below, which contains one or more GPG keys:

// pub <encryption algorithm>/<gpg-short-id> <date> [SC]

pub rsa3072/87E39614 2024-01-22 [SC]
DD28C4154EB791431BFE515AF3B24FB387E39614
uid [ultimate] Ankit Kumar (..) <example@gmail.com>
sub rsa3072/9FFEC7CE 2024-01-22 [E]

pub ed25519/2BF3E5DA 2023-10-02 [SC] [expires: 2026-10-01]
DF0A28897E1A532A6BF5C4B9B9EDCC712BF3E5DA
uid [ unknown] Ankit <example@gmail.com>
sub cv25519/5CD8CFFB 2023-10-02 [E] [expires: 2026-10-01]

Pick one. Look carefully at the format (in the first line of the above output): “pub <encryption algorithm>/<gpg-short-id> <date> [SC]”

<gpg-short-id> will be OSS_SIGNING_KEY_ID at later stage

Get staging profile Id | OSS_STAGING_PROFILE_ID

https://s01.oss.sonatype.org/#stagingProfiles;<OSS_STAGING_PROFILE_ID>

Generating base64 file for gpg key | OSS_SIGNING_KEY

Run the below command a base 64 string will be generated and password is what you set while creating gpg key

gpg --export-secret-keys <gpg-short-id> | base64

Code Changes

Configure root level build.gradle of your project [reference]

plugins {
....
id 'io.github.gradle-nexus.publish-plugin' version '1.1.0'
}

// only for users registered in Sonatype after 24 February 2021
nexusPublishing {
repositories {
sonatype {
username = System.getenv("OSS_USERNAME")
password = System.getenv("OSS_PASSWORD")
stagingProfileId = System.getenv("OSS_STAGING_PROFILE_ID")

nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}

Create publish-package.gradle [reference]

Creating a separate file will help to easily reuse in multimodular project or any other project

Note : You can configure version for each individual module also, to do so remove VERSION from below and add it at module level gradle

// Please go through the file and do the needful change
apply plugin: 'maven-publish'
apply plugin: 'signing'

ext {
GROUP_ID = "io.github.pseudoankit"
VERSION = (System.getenv("RELEASE_TAG_NAME") ?: "SNAPSHOT").replace("v", "")

SITE_URL = 'https://github.com/pseudoankit/coachmark'
GIT_URL = 'https://github.com/pseudoankit/coachmark.git'

POM_DESCRIPTION = "Compose library to add coachmark"
POM_URL = SITE_URL
}

signing {
useInMemoryPgpKeys(
System.getenv("OSS_SIGNING_KEY_ID"),
System.getenv("OSS_SIGNING_KEY"),
System.getenv("OSS_SIGNING_PASSWORD"),
)
sign publishing.publications
}

// If you want to publish your sources as well
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
from android.sourceSets.main.kotlin.srcDirs
}

artifacts {
archives androidSourcesJar
}

afterEvaluate {
publishing {
publications {
release(MavenPublication) {

groupId GROUP_ID
artifactId ARTIFACT_ID
version VERSION

from components.release
artifact androidSourcesJar

pom {
name = ARTIFACT_ID
description = POM_DESCRIPTION
url = POM_URL
licenses {
license {
name = "The Apache Software License, Version 2.0"
url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
}
}

developers {
developer {
id = 'pseudoankit'
name = 'Ankit Kumar'
email = 'lostankit7@gmail.com'
}
}

scm {
connection = GIT_URL
developerConnection = GIT_URL
url = SITE_URL
}
}
}
}
}
}

Configure the build.gradle file of each module [reference]

....
apply from: '../gradle/publish-package.gradle'
ext {
ARTIFACT_ID = "coachmark"
}

Setting up environment variables

Below are steps to do in mac you can check for other OS

Open Terminal
run vim ~/.zshrc
press space
press e
press i

now add these lines

export RELEASE_TAG_NAME=<dummy version anyways we will get it from github release>
export OSS_STAGING_PROFILE_ID=<steps above>
export OSS_USERNAME=<oss jira user name / mentioned above>
export OSS_PASSWORD=<oss jira user password / mentioned above>
export OSS_SIGNING_KEY_ID=<<gpg-short-id> steps mentioned above>
export OSS_SIGNING_PASSWORD=<password which you entered while creating gpg / mentioned above>
export OSS_SIGNING_KEY=<steps mentioned above>

press esc
type :qw -> enter
source ~/.zshrc

Publish Libraries

Publish to Local Maven

Before publishing to Maven, first try to publish the packages into local Maven.

./gradlew publishToMavenLocal

This will publish all your modules that are configured for Maven into local Maven.

You can test your libraries, by importing them into different projects. For that, you first need to add mavenLocal() as one of the lists of repositories and then import the library as dependencies in the gradle file as usual:

implementation 'io.github.pseudoankit:coachmark:1.7.0'

Publish SNAPSHOT to Maven

Snapshot libraries are useful when you are not formally releasing the libraries, but want your audience/testers to test it by using it. For that, you first need to append ‘-SNAPSHOT’ to your version and run

./gradlew publishReleasePublicationToSonatypeSnapshotRepository

Once published, you should be able to see your libraries on location:

https://s01.oss.sonatype.org/content/repositories/snapshots/io/github/<pseudoankit>/

Publish the Final Release to Maven

./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository

Once published you should be able to see your libraries on location:

https://s01.oss.sonatype.org/content/repositories/releases/io/github/pseudoankit/

Automating release via Github Action [reference]

Create a file publish.yml under project/.github/workflows/...

name: Publish

# This block defines that action will be triggered when we do a github release
on:
release:
types: [ created ]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup JDK
uses: actions/setup-java@v1
with:
java-version: 17

- name: Publish Artifact
env:
# fetching the release version tag
RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
OSS_USERNAME: ${{ secrets.OSS_USERNAME }}
OSS_PASSWORD: ${{ secrets.OSS_PASSWORD }}
OSS_STAGING_PROFILE_ID: ${{ secrets.OSS_STAGING_PROFILE_ID }}
OSS_SIGNING_KEY_ID: ${{ secrets.OSS_SIGNING_KEY_ID }}
OSS_SIGNING_PASSWORD: ${{ secrets.OSS_SIGNING_PASSWORD }}
OSS_SIGNING_KEY: ${{ secrets.OSS_SIGNING_KEY }}
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository

Setting up environment variables in github project

  • Navigate to your repository
  • Go to Settings
  • Under Secrets And Variables section, navigate to Actions tab
  • New repository secret, add all key-values we added in terminal 🔝

Release library via action

  • Navigate to your repository
  • Some where on right, click on Releases
  • Draft a new release
  • Choose tag <version> (eg: v1.0.0)
  • Publish release

Wohoo! You just published your library 🚀

I didn’t face this problem, but we might have to do the following as recommended in this article.:

If you are releasing for the first time, do not forget to comment on the Jira tracker ticket, letting Sonatype know that you have completed a release. This is for them to activate some kind of sync process.

Thank you for reading the article, hope you found it informative and helpful for streamlining your development workflow.

Here’s the complete changelist : github.com

If you have any questions or need further assistance, please don’t hesitate to reach out on linkedin

Additionally, I invite you to explore my Coachmark library — A Jetpack Compose library to provide seamless onboarding experience to users.
Feel free to check out my GitHub profile for more projects and contributions.

Happy coding!

Few References taken from :-
https://thsaravana.github.io/blog/publish-android-library-maven-central/
https://medium.com/@vivekvashistha/how-to-publish-android-libraries-on-maven-central-in-2023-a96e3c327008

--

--