Writing a Gradle Plugin with Kotlin


Motivation

I recently started a project for making migrations for Keycloak possible in a liquibase-like style. To be able to invoke this migrations from gradle I had to write a gradle plugin. I didn’t find a good ressource how to do so, so I decided to make a quick write up.

Basics

Gradle is a build automation tool from the java ecosystem. It has a lot of plugins for various use cases.

Buildfiles are describedin Groovy as default but Gradle recently added the possibility to also write build scripts in a Kotlin DSL.

The Kotlin support will hit version 1.0 with Gradle 5.0.

Getting started

To start the plugin project we have to initialize a new gradle project first:

mkdir kotlintestplugin
cd kotlintestplugin
gradle init --dsl kotlin

We start with a really basic build file. We just need gradleApi() as special dependency.

build.gradle.kts

plugins {
    kotlin("jvm") version "1.3.0"
}

dependencies {
    compile(kotlin("stdlib"))
    compile(kotlin("reflect"))
    implementation(gradleApi())
    implementation(localGroovy())
}

repositories {
    jcenter()
}

Defining the task

At first we will start with defining the plugin task and then construct the rest of the plugin structure.

src/main/de/klg71/kotlintestplugin/KotlinTestPlugin.kt

open class TestTask : DefaultTask() {
    @TaskAction
    fun testAction() {
        println("Hello World")
    }
}

We simply created a task to print some “Hello World” message.

Creating the Plugin

We add a new class to create the real plugin for gradle.

src/main/de/klg71/kotlintestplugin/KotlinTestPlugin.kt

open class TestTask : DefaultTask() {
    @TaskAction
    fun testAction() {
        println("Hello World")
    }
}

// The plugin needs to inherit from Plugin<Project>
open class KotlinTestPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        // Register our defined task
        project.tasks.create<TestTask>("kotlinTestPlugin", TestTask::class.java).run {
            // Set description and group for the task
            description = "Print test message"
            group = "TestPlugin"
        }
    }
}

Finishing the plugin

To be able to apply our plugin to a project we need to create a small manifest file describing the plugin.

src/main/resources/META-INF/gradle-plugins/de.klg71.kotlintestplugin.properties

implementation-class=de.klg71.kotlintestplugin.KotlinTestPlugin

We also need a gradle.properties file to set group, version and desciption.

gradle.properties

group = de.klg71
version = 0.0.1-SNAPSHOT
description = kotlintestplugin

Building the plugin

Now we can just execute the jar gradle task to create the plugin binary.

gradle jar

The jar can now be found unter build/libs/kotlintestplugin-0.0.1-SNAPSHOT.jar.

We will need it in the next step to test the plugin.

Testing the plugin

We create a new gradle project to test our plugin.

mkdir kotlin_plugin_test_project
gradle init --dsl kotlin
mkdir libs

Now copy the jar created above into the newly created libs directory.

The last thing to do is to apply this plugin to our test project: build.gradle.kts

buildscript {
    repositories {
        flatDir {
            dirs("libs")
        }
    }
    dependencies {
        classpath("de.klg71:kotlintestplugin:0.0.1-SNAPSHOT")
    }
}

apply(plugin="de.klg71.kotlintestplugin")

We can now see the plugin task if we execute the tasks target. And the task kotlinTestPlugin to print the message.

gradle tasks

>>>>
TestPlugin tasks
----------------
kotlinTestPlugin - Print test message

gradle kotlinTestPlugin

>>>>
> Task :kotlinTestPlugin
Hello World

Wrapping it up

We created a simple gradle plugin in Kotlin to print a message. We then applied this plugin to a sample project.

You can find the plugin and testproject on Github:

Another example plugin example: