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
- Register Group ID on Maven by raising a Jira Ticket
- Generate GPG Keys | OSS_SIGNING_KEY_ID
- Get staging profile Id | OSS_STAGING_PROFILE_ID
- Generating base64 file for gpg key | OSS_SIGNING_KEY
- Configure root level build.gradle of project
- Create publish-package.gradle
- Configure the build.gradle file of each module
- Setting up environment variables
- Publish to Local Maven
- Publish SNAPSHOT to Maven
- Publish the Final Release to Maven
- Automating release via Github Action
- 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
- Go to Sonatype -> Staging Repository
- Click on 1st row and check the web url you will find a alphanumeric at the end, that’s our 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