ometimes, developers want to keep their Kotlin Multiplatform libraries private instead of sharing them with the world. Why? Maybe they’ve got some super-secret code they want to protect, or they’ve got special tools just for their team’s use. By keeping these libraries private, developers can control who gets to see their code, keeping it safe and sound. Plus, it makes managing dependencies and versions easier, especially in places where only certain folks should have access.
While we previously explored the process of publishing Kotlin Multiplatform Libraries to Maven Central via Sonatype Central, in this guide, we will be looking at the steps involved in publishing private Kotlin Multiplatform libraries to GitHub Packages. GitHub Packages is a service that lets you store different types of packages, kind of like a digital toolbox. You can decide who gets access to your packages, and it works smoothly with other GitHub tools.
Throughout the guide, we will use the MathLibGuide project introduced in the previous article as our example project. However, readers can adapt these steps to their own Kotlin Multiplatform projects as needed. Let’s get started!
Generating a GitHub Personal Access Token
First create a Personal Access Token for your GitHub account by navigating to Settings > Developer Settings > Personal access tokens > Tokens (classic):
Enter a Note for the token such as GithubPackagesSample
and choose your preferred expiration duration. Then, select the write:packages
scope which should auto-select the the read:packages
and repo
scopes. These permissions are necessary for publishing and importing packages via GitHub Packages.
Next, click on the Generate token button at the bottom of the page to create the token. Make sure to copy this token and store it securely, as it will be used later on.
Publishing To GitHub Packages
Next, include the gradle-maven-publish-plugin plugin, created by Niklas Baudy, in the build.gradle.kts file of the math-lib
module and then sync your project:
plugins {
id("com.vanniktech.maven.publish") version "0.28.0"
}
This plugin sets up a publish task for you, making it a breeze to upload all your Kotlin Multiplatform library pieces to any Maven instance. Afterward, create a gradle.properties
file in your project’s root directory if one does not already exist and include the following properties:
githubPackagesUsername=<GITHUB_USER_NAME>
githubPackagesPassword=<GITHUB_PERSONAL_ACCESS_TOKEN>
githubPackagesUsername
: Your GitHub username.githubPackagesPassword
: Your GitHub Personal Access Token
As responsible developers, ensuring the security of credentials such as the above should be a must. Ideally, these two properties should never be committed to version control and should remain private to each developer’s environment. However, in projects involving version control, it is beneficial to consider automated publishing through CI/CD pipelines, such as GitHub Actions. By setting these properties as environment variables within the CI/CD workflow, they can be securely managed and protected from exposure in version controlled files. We will look at how to implement this with GitHub Actions later on.
The next step to enable publishing to GitHubPackages
is to configure your POM by adding the following block to your math-lib/build.gradle.kts
, replacing all the placeholders in brackets with your own values:
publishing { | |
repositories { | |
maven { | |
name = "githubPackages" | |
url = uri("https://maven.pkg.github.com/<GITHUB_USER_NAME>/MathLibGuide") | |
credentials(PasswordCredentials::class) | |
} | |
} | |
} | |
mavenPublishing { | |
// Define coordinates for the published artifact | |
coordinates( | |
groupId = "<YOUR_PROJECT_PACKAGE_NAME>", | |
artifactId = "math-lib", | |
version = "1.0.0" | |
) | |
// Configure POM metadata for the published artifact | |
pom { | |
name.set("Math KMP Library") | |
description.set("Sample Kotlin MultiPlatform Library Test") | |
inceptionYear.set("2024") | |
url.set("https://github.com/<GITHUB_USER_NAME>/MathLibGuide") | |
licenses { | |
license { | |
name.set("MIT") | |
url.set("https://opensource.org/licenses/MIT") | |
} | |
} | |
// Specify developers information | |
developers { | |
developer { | |
id.set("<GITHUB_USER_NAME>") | |
name.set("<GITHUB_ACTUAL_NAME>") | |
email.set("<GITHUB_EMAIL_ADDRESS>") | |
} | |
} | |
// Specify SCM information | |
scm { | |
url.set("https://github.com/<GITHUB_USER_NAME>/MathLibGuide") | |
} | |
} | |
} |
In the code snippet provided, the PasswordCredentials class from the gradle-maven-publish-plugin plugin is used to authenticate with GitHub Packages. This class automatically retrieves the required username and password values from the gradle.properties file. Specifically, it references the githubPackagesUsername and githubPackagesPassword properties defined in the gradle.properties file, ensuring secure authentication with GitHub Packages.
Before we go ahead and publish, make sure your androidTarget block has a publishLibraryVariants if you’re publishing android artifacts:
kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "1.8"
}
}
publishLibraryVariants("release", "debug")
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "math-lib"
isStatic = true
}
}
sourceSets {
commonMain.dependencies {
}
commonTest.dependencies {
implementation(libs.kotlin.test)
}
}
}
android {
namespace = "io.github.<GITHUB_USER_NAME>"
compileSdk = 34
defaultConfig {
minSdk = 28
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
Next, let’s publish your Kotlin Multiplatform artifacts to GitHub Packages. To do this, open your terminal in the Android Studio IDE, and enter the following command to initiate the publishing process:
./gradlew publishAllPublicationsToGithubPackagesRepository
This command triggers the Gradle task to publish your pre-built artifacts to GitHub Packages. If the artifacts have not been previously built, Gradle will handle the necessary build steps before publishing them. The process typically takes a couple of minutes to complete. After the Gradle command completes successfully, navigate to the Packages tab on your GitHub profile to confirm that your artifacts have been published.
Job Offers
With regards to CI/CD, platforms like GitHub Actions enable us to automate the entire process outlined above using a workflow file. Let’s briefly look at how to set this up.
First, ensure you have a GitHub repository for your sample project. If you don’t already have one, create it. Then, navigate to the repository settings by clicking on Settings > Secrets and variables > Actions:
Here, we’ll need to set up some environment variables or secrets that will be used in our GitHub actions workflow:
GH_PACKAGES_USER_NAME
: Your GitHub username.GH_PACKAGES_PASSWORD
: Your GitHub Personal Access Token.
These credentials will be used to authenticate and perform actions on your behalf during the CI/CD process.
Next, let’s set up the GitHub Actions workflow. Create a new directory named ./github/workflows
in the root of your project. Then, create a file named publish.yml
with the following contents:
name: Publish Artifacts | |
on: | |
workflow_dispatch: | |
jobs: | |
build: | |
name: Build | |
runs-on: macos-latest | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
- name: Setup Java | |
uses: actions/setup-java@v4 | |
with: | |
distribution: 'zulu' | |
java-version: '17' | |
- name: Setup Gradle | |
uses: gradle/actions/setup-gradle@v3 | |
- name: Add Gradle Properties | |
env: | |
GITHUB_PACKAGES_USER_NAME: ${{ secrets.GH_PACKAGES_USER_NAME }} | |
GITHUB_PACKAGES_PASSWORD: ${{ secrets.GH_PACKAGES_PASSWORD }} | |
run: | | |
echo "githubPackagesUsername=${GITHUB_PACKAGES_USER_NAME}" >> gradle.properties | |
echo "githubPackagesPassword=${GITHUB_PACKAGES_PASSWORD}" >> gradle.properties | |
- name: Setup Xcode | |
uses: maxim-lobanov/setup-xcode@v1 | |
with: | |
xcode-version: latest-stable | |
- name: Publish To GitHub Packages | |
run: | | |
./gradlew publishAllPublicationsToGithubPackagesRepository |
After setting up the GitHub Actions workflow, commit and push the changes to your GitHub repository. Once you’ve pushed your changes, navigate to the Actions tab in your GitHub repository. Here, you should see the newly created workflow named Publish Artifacts. If the workflow hasn’t started automatically, you can manually trigger it by clicking on Run workflow.
After the GitHub Actions workflow completes, you should find the artifacts in the Packages tab on your GitHub profile.
To include or import the published library in a project, ensure that the project has a gradle.properties
file in its root directory containing the githubPackagesUsername
and githubPackagesPassword
properties. Next, modify your settings.gradle
file to include the GitHub Packages repository in both the pluginManagement
and dependencyResolutionManagement
repositories blocks:
pluginManagement { | |
repositories { | |
google() | |
gradlePluginPortal() | |
mavenCentral() | |
maven { | |
name = "gitHubPackages" | |
url = uri("https://maven.pkg.github.com/<GITHUB_USER_NAME>/MathLibGuide") | |
credentials(PasswordCredentials::class) | |
} | |
} | |
} | |
dependencyResolutionManagement { | |
repositories { | |
google() | |
mavenCentral() | |
maven { | |
name = "gitHubPackages" | |
url = uri("https://maven.pkg.github.com/<GITHUB_USER_NAME>/MathLibGuide") | |
credentials(PasswordCredentials::class) | |
} | |
} | |
} |
Replace <GITHUB_USER_NAME>
with your GitHub username. After updating the settings.gradle
file, sync your project. Then include the library like so replacing <YOUR_PROJECT_PACKAGE_NAME>
with yours:
implementation("<YOUR_PROJECT_PACKAGE_NAME>:math-lib:1.0.0")
Congratulations on successfully publishing your Kotlin Multiplatform libraries using GitHub Packages! I hope this guide has been helpful in navigating the process and that you’re now equipped to manage your libraries with confidence.
Happy coding!
Special thanks to Denis Brandi , Nate Ebel and Mayowa Egbewunmi for taking the time to review this article.
This article is previously published on proandroiddev.com