Publish Multi-module Private Android Library to jFrog
--
Scenario:
- You are building an Android library that can be used only by those with access.
- The Android library has multiple modules.
- Your library is on a private repo on GitHub or BitBucket.
debug
version of the library should be published on every merge to master.release
version of the library should be published on every tag pushed.- You need to use jFrog Artifactory to distribute your library.
Step 1: Prerequisites
Access
You need to have write access to the jFrog repo in which you want to publish your artifacts.
jFrog identity token
jFrog identity token to publish the artifacts. Follow the below steps to generate an identity token:
- Open your jFrog, click on your username on the top right, and open Edit profile.
- Under Authentication Settings, click on Generate an Identity Token. Make sure to keep a note of this token.
Adding secrets to GitHub
You need to add your jFrog username and the identity token to your GitHub secrets so that GitHub Actions can build your library and publish directly to jFrog Artifactory.
- Go to your repository Settings.
- Under the Secrets and variables menu, click on Action.
- Here, click on New repository secret and add the following secrets:
JFROG_USERNAME
= Your jFrog username
JFROG_PASSWORD
= jFrog identity token that you created earlier.
Step 2: Publishing script
Imagine you have the following modules in your library project
app
— This is the sample app that implements your library.mylib-client
— This is the main client module that is the entry to this library.mylib-resources
— This is a module that has all the string, drawable, and other resources.mylib-services
— This module contains the data layer.mylib-ui
— This module contains the UI layer.
During publishing the library, you must skip the app module and publish only mylib-client
the module. The other 3 modules will be added as a dependency to the main module.
Let’s get straight into integration now.
Open your project-level build.gradle
file and add the following under the plugins
section:
id 'com.jfrog.artifactory' version '4.29.1' apply false
Next, create a new subprojects
section. We need to create this section to make sure all the modules are evaluated.
subprojects {
apply plugin: 'maven-publish'
apply plugin: 'com.jfrog.artifactory'
afterEvaluate {
plugins.withId('com.android.library') {
println(project.name)
publishing {
publications {
release(MavenPublication) {
groupId = <YOUR_GROUP_ID>
artifactId = project.getName()
version = System.getenv("SDK_VERSION")
afterEvaluate {
from components.release
}
pom {
name = <YOUR_SDK_NAME>
description = <YOUR_SDK_DESCRIPTION>
url = <URL_TO_YOUR_SDK_OR_COMPANY>
developers {
developer {
id = <OPTIONAL_DEVELOPER_ID>
name = <OPTIONAL_DEVELOPER_NAME>
email = <OPTIONAL_DEVELOPER_EMAIL>
}
}
}
}
}
repositories {
maven {
url = System.getenv("REPO_URL")
credentials {
username = System.getenv("JFROG_USERNAME")
password = System.getenv("JFROG_PASSWORD")
}
}
}
}
}
}
}
Okay, let's break it down.
subprojects
will traverse each module of your library.
release(MavenPublication)
will publish the release
version of your library.
YOUR_GROUP_ID
= Something like com.companyname
. With this, your library can then be accessed in the following way:
implementation "com.companyname.mylib-client:1.0.0"
Under repositories.maven
section, url
, username
and password
will be taken from GitHub Secrets. More about this is in the GitHub Actions section.
Step3 — Make the modules ready
Now that you have added the publishing script, we need to make sure that all the submodules we want should be added as an api
dependency and not implementation
dependency.
For example, change
implementation project(‘:mylib-ui’)
→ api project(‘:mylib-ui’)
This is a crucial step. Skipping this will not add the submodules to your main module in the published library instead you will have to add all your submodules as separate dependencies in the host app.
Step 4 — GitHub workflow to publish artifacts
Goto GitHub Actions and create a new workflow called publish_debug.yml
name: Publish Artifactory - Debug
on:
workflow_dispatch:
push:
branches:
- master
jobs:
tests:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Run tests - Debug
run: ./gradlew clean testDebug
publish:
needs: [tests]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Publish
env:
SDK_VERSION: ${{ format('1.{0}.{1}', github.run_number, github.run_attempt) }}
REPO_URL: "https://YOUR_JFROG_DOMAIN/artifactory/YOUR_JFROG_REPO/"
JFROG_USERNAME: ${{ secrets.JFROG_USERNAME }}
JFROG_PASSWORD: ${{ secrets.JFROG_PASSWORD }}
run: ./gradlew publish
Now, whenever a PR is merged to the master branch, this workflow will run.
It will create a version for your library, and publish the artifacts to the REPO_URL
with the credentials that you have provided with JFROG_USERNAME
and JFROG_PASSWORD
.
Similarly, you can create another workflow called publish_release.yml
to publish the release version of the library every time you create a new release in GitHub.
name: Publish Artifactory - Release
on:
workflow_dispatch:
release:
types: [released]
jobs:
tests:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Run tests - Release
run: ./gradlew clean testRelease
publish:
needs: [tests]
runs-on: ubuntu-20.04
steps:
- name: SDK release version
run: |
VERSION=${GITHUB_REF_NAME#v}
echo "SDK_VERSION=$VERSION" >> $GITHUB_ENV
echo Releasing SDK version ${VERSION}
- uses: actions/checkout@v2
- name: Publish
env:
REPO_URL: "https://YOUR_JFROG_DOMAIN/artifactory/YOUR_JFROG_REPO/"
JFROG_USERNAME: ${{ secrets.JFROG_USERNAME }}
JFROG_PASSWORD: ${{ secrets.JFROG_PASSWORD }}
run: ./gradlew publish
Note that the version of your library in the release version is the tag that you push.
That’s it. You will be able to see your library added under artifacts in jFrog.
Step 5 — Accessing the library
Now that the library is published, we would like to add it as a dependency in one of our projects.
Open the gradle.properties
file and add the following
mavenUser=YOUR_JFROG_USERNAME_HERE
mavenPassword=YOUR_JFROG_IDENTITY_TOKEN_HERE
Next, open your project-level build.gradle
file and the following:
allprojects {
repositories {
...
maven {
url "YOUR JFROG REPO URL HERE"
credentials {
username "$mavenUser"
password "$mavenPassword"
}
}
}
}
With this, you have added credentials to access the private artifacts on jFrog.
Now you can go ahead and add your library as a dependency in the app-level build.gradle
file like the below:
implementation "com.companyname.mylib-client:1.0.0"
That’s it. You should now have the library added as a dependency.