I have been heavily using other CI/CD platforms like GitLab, BitBucket, Jenkins, and Azure DevOps but I can definitely say GitHub nailed it. It has a different and easy-to-use approach and I am surprised that you can add custom runners for your CI/CD pipeline.
I will create a very simple Kotlin application to show how to deploy a library in a private Maven repository. I am going to use Repsy for Maven repository hosting. It gives 3 GB of free storage and should be sufficient for most cases.
Let's create a Gradle project, your IDE will help with this, or you can install Gradle CLI from the official gradle site or you can use SdkMan for this purpose.
sdk i gradle
Gradle CLI will help you to bootstrap your project.
mkdir hello-actions-kotlin-lib
cd hello-actions-kotlin-lib
gradle init
Gradle will ask us a bunch of questions. I will select the library
type for project generation
Select the type of project to generate:
1: basic
2: application
3: library
4: Gradle plugin
Enter selection (default: basic) [1..4] 3
Kotlin for programming language selection. I'm happy to see plenty of options there.
Select implementation language:
1: C++
2: Groovy
3: Java
4: Kotlin
5: Scala
6: Swift
Enter selection (default: Java) [1..6] 4
And going to use Kotlin DSL instead of Groovy.
Select build script DSL:
1: Kotlin
2: Groovy
Enter selection (default: Kotlin) [1..2] 1
Just press enter for the default project name or you can enter another one suitable for you.
Project name (default: hello-actions-kotlin-lib):
For the source package selection, I am going to use my GitHub TLD but feel free to use your package structure.
Source package (default: hello.actions.kotlin.lib): com.github.firatkucuk.hello_actions_kotlin_lib
As a final question gradle will ask you the Java version. You may want to select the Latest LTS version (21) or one one the safest ones 8
or 11
. I'll choose 17.
Enter target version of Java (min. 7) (default: 21): 17
It seems a little bit long but that’s OK. Gradle will create a simple Library.kt
file. Let’s rename it Hello.kt
and change the content.
package com.github.firatkucuk.hello_actions_kotlin_lib;
class Hello {
fun sayHello(text: String): String {
return "Hello $text"
}
}
And same for the test file LibraryTest.kt
. Let's rename it to HelloTest.kt
and change the test file content to:
package com.github.firatkucuk.hello_actions_kotlin_lib
import kotlin.test.Test
import kotlin.test.assertEquals
class HelloTest {
@Test fun sayHelloMethodReturnsHello() {
val classUnderTest = Hello()
assertEquals("Hello World", classUnderTest.sayHello("World"), "sayHello method should return 'Hello World'")
}
}
Now, we can test the build operation:
gradle build
The next phase is publishing our library to our private maven repository in repsy.io. After signup, repsy creates a default repository that can be used with the account password. So you only need to sign up, and that’s all.
Let’s modify our build.gradle.kts
file for publishing the artifact. The most important part is adding a maven-publish
plugin and a publishing section with the credentials from repsy.
version = "1.0.0"
plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
id("org.jetbrains.kotlin.jvm") version "1.9.10"
// Apply the java-library plugin for API and implementation separation.
`java-library`
`maven-publish`
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
val repsyUrl: String by project
val repsyUsername: String by project
val repsyPassword: String by project
publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
}
}
repositories {
maven {
url = uri(repsyUrl)
credentials {
username = repsyUsername
password = repsyPassword
}
}
}
}
dependencies {
// Use the Kotlin JUnit 5 integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
// Use the JUnit 5 integration.
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// This dependency is exported to consumers, that is to say found on their compile classpath.
api("org.apache.commons:commons-math3:3.6.1")
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation("com.google.guava:guava:32.1.1-jre")
}
// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}
Our project implementation is completed. Let’s create git integration of our project. First, create an empty git project called hello-actions-kotlin-lib
on GitHub. After that, we commit the changes and push files to GitHub.
git init
git add .
git commit -m "initial commit"
git remote add origin git@github.com:YOUR_GITHUB_USER_NAME/hello-actions-kotlin-lib.git
git push origin main
The next step is integrating your project with GitHub Actions. Go to https://github.com/YOUR_USER_NAME/hello-actions-kotlin-lib/actions/new
Please Find the Java with Gradle Action. Then you can click the Set up this workflow button. An online editor will be opened up.
Let’s directly commit the changes and we’re gonna see our Action will run immediately. GitHub action will fail so please ignore this. It requires some properties file we’re gonna add properties as GitHub secret.
We need to create a GitHub secret for our gradle.properties
file. But because of the limitations. GitHub cannot use file content as secrets. GitLab has the same restriction once upon a time then they’ve introduced File types but we need to create a text file our local computer. The content should be something like this:
repsyUrl=https://repo.repsy.io/mvn/YOUR_REPSY_USERNAME/default
repsyUsername=YOUR_REPSY_USERNAME
repsyPassword=YOUR_REPSY_PASSWORD
We need to encode this with base64. There are many online base64 converters. If you’re using Mac/Linux it should be easy like this:
base64 -w0 gradle.properties
Let's copy the output and create a secret. Go to https://github.com/YOUR_USER_NAME/hello-actions-kotlin-lib/settings/secrets
Add a GitHub secret called GRADLE_PROPERTIES and paste the encoded string into it.
Now we can open our pipeline configuration file and make the latest changes. Go To https://github.com/YOUR_USER_NAME/hello-actions-kotlin-lib/blob/master/.github/workflows/gradle.yml
and click the edit button. We will add some extra steps for injecting Gradle properties.
name: Java CI with Gradle
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.1
- name: Set up JDK 17
uses: actions/setup-java@v3.13.0
with:
java-version: 17
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
env:
GRADLE_PROPERTIES: ${{ secrets.GRADLE_PROPERTIES }}
run: mkdir -p ~/.gradle && echo $GRADLE_PROPERTIES | base64 -d > ~/.gradle/gradle.properties && cat ~/.gradle/gradle.properties && ./gradlew build
- name: publish
run: ./gradlew publish
That’s all you can find the source code here.
Top comments (0)