DEV Community

Fırat Küçük
Fırat Küçük

Posted on • Originally published at Medium on

Creating GitHub Action to Deploy Projects into a Private Maven Repository

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
Enter fullscreen mode Exit fullscreen mode

Gradle CLI will help you to bootstrap your project.

mkdir hello-actions-kotlin-lib
cd hello-actions-kotlin-lib
gradle init
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

And going to use Kotlin DSL instead of Groovy.

Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Kotlin) [1..2] 1
Enter fullscreen mode Exit fullscreen mode

Just press enter for the default project name or you can enter another one suitable for you.

Project name (default: hello-actions-kotlin-lib):
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
    }
}
Enter fullscreen mode Exit fullscreen mode

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'")
    }
}

Enter fullscreen mode Exit fullscreen mode

Now, we can test the build operation:

gradle build
Enter fullscreen mode Exit fullscreen mode

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()
}

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

That’s all you can find the source code here.

Top comments (0)