Part 1: Initializing the Project
Learn the basics of developing Gradle plugins starting with gradle init.
Step 0: Before you Begin
Before we start, make sure you have everything you need:
-
Gradle Installed: Check that you have Gradle installed by running
gradle -vin your terminal. If not, follow the link to the installation guide. -
IntelliJ IDEA: Install the free IntelliJ IDEA Community Edition. It’s a great tool for working with Gradle projects.
Step 1: Initializing the Project
Let’s get started by creating our project.
First, create a new directory called plugin-tutorial and navigate into it:
$ mkdir plugin-tutorial
$ cd plugin-tutorial
Now, run the gradle init command to automatically generate a basic plugin project.
You can build this plugin in either Groovy or Kotlin:
$ gradle init --type kotlin-gradle-plugin --dsl kotlin
$ gradle init --type groovy-gradle-plugin --dsl groovy
When prompted for additional options, just accept the default values.
| All examples in this tutorial are based on a macOS environment. |
Step 2: Understanding the Project Layout
After gradle init finishes, you’ll have a new project structure.
The plugin-tutorial directory is our root project, and inside, there’s a subproject named plugin where we’ll do most of our work.
The project should look like this:
.
├── gradle (1)
│ ├── libs.versions.toml (2)
│ └── wrapper
├── gradlew (3)
├── gradlew.bat (3)
├── settings.gradle.kts (4)
└── plugin/
├── build.gradle.kts (5)
└── src
├── main
│ └── kotlin (6)
│ └── org/example
│ └── PluginTutorialPlugin.kt
├── test
│ └── kotlin (7)
│ └── org/example
│ └── PluginTutorialPluginTest.kt
└── functionalTest
└── kotlin (8)
└── org/example
└── PluginTutorialPluginFunctionalTest.kt
| 1 | This folder holds the wrapper files that allow us to run Gradle without a local installation. |
| 2 | This is a version catalog, a tool for managing all your project’s dependencies in one place. |
| 3 | These are the Gradle wrapper scripts for macOS/Linux and Windows. |
| 4 | This file defines the name of our build and includes our plugin subproject. |
| 5 | The build script for our plugin subproject. This is where we’ll add our dependencies and configure the plugin. |
| 6 | The default source folder for our new plugin. |
| 7 | The default folder for unit tests. |
| 8 | The default folder for functional tests. |
.
├── gradle (1)
│ ├── libs.versions.toml (2)
│ └── wrapper
├── gradlew (3)
├── gradlew.bat (3)
├── settings.gradle (4)
└── plugin/
├── build.gradle (5)
└── src
├── main
│ └── groovy (6)
│ └── org/example
│ └── PluginTutorialPlugin.groovy
├── test
│ └── groovy (7)
│ └── org/example
│ └── PluginTutorialPluginTest.groovy
└── functionalTest
└── groovy (8)
└── org/example
└── PluginTutorialPluginFunctionalTest.groovy
| 1 | This folder holds the wrapper files that allow us to run Gradle without a local installation. |
| 2 | This is a version catalog, a tool for managing all your project’s dependencies in one place. |
| 3 | These are the Gradle wrapper scripts for macOS/Linux and Windows. |
| 4 | This file defines the name of our build and includes our plugin subproject. |
| 5 | The build script for our plugin subproject. This is where we’ll add our dependencies and configure the plugin. |
| 6 | The default source folder for our new plugin. |
| 7 | The default folder for unit tests. |
| 8 | The default folder for functional tests. |
Step 3: Review the Gradle Build File
Let’s take a look at the build.gradle(.kts) file inside the plugin directory.
This is where the magic happens.
When you’re writing a plugin, you’ll use the java-gradle-plugin to:
-
Automatically generate the necessary plugin metadata.
-
Add plugin development conventions and tasks.
-
Simplify the publishing process.
This is what the gradlePlugin {} and plugins {} block looks like:
plugins {
// Apply the Java Gradle plugin development plugin to add support for developing Gradle plugins
`java-gradle-plugin`
// Apply the Kotlin JVM plugin to add support for Kotlin.
alias(libs.plugins.kotlin.jvm)
}
gradlePlugin {
// Define the plugin
val greeting by plugins.creating {
id = "org.example.greeting"
implementationClass = "org.example.PluginTutorialPlugin"
}
}
plugins {
// Apply the Java Gradle plugin development plugin to add support for developing Gradle plugins
id 'java-gradle-plugin'
// Apply the Groovy plugin to add support for Groovy
id 'groovy'
}
gradlePlugin {
// Define the plugin
plugins {
greeting {
id = 'org.example.greeting'
implementationClass = 'org.example.PluginTutorialPlugin'
}
}
}
-
gradlePlugin {}: This is where you configure the plugins you’re authoring. -
val greeting by plugins.creating {}orplugins.greeting {}: This registers a new plugin definition with the IDorg.example.greeting. -
implementationClass = "org.example.PluginTutorialPlugin": This points to the main class that contains your plugin’s logic.
Step 4: Review the Plugin Code
The plugin code is a simple "Hello, World!" example that gradle init generated for us.
You can find it at `plugin/src/main/kotlin/org/example/PluginTutorialPlugin.kt`:
You can find it at `plugin/src/main/groovy/org/example/PluginTutorialPlugin.groovy`:
package org.example
import org.gradle.api.Project
import org.gradle.api.Plugin
/**
* A simple 'hello world' plugin.
*/
class PluginTutorialPlugin: Plugin<Project> {
override fun apply(project: Project) {
// Register a task
project.tasks.register("greeting") { task ->
task.doLast {
println("Hello from plugin 'org.example.greeting'")
}
}
}
}
package org.example
import org.gradle.api.Project
import org.gradle.api.Plugin
/**
* A simple 'hello world' plugin.
*/
class PluginTutorialPlugin implements Plugin<Project> {
void apply(Project project) {
// Register a task
project.tasks.register("greeting") {
doLast {
println("Hello from plugin 'org.example.greeting'")
}
}
}
}
-
Plugin<Project>: Our plugin needs to implement this interface to work with aProjectobject. -
apply(): This method is the entry point. Gradle calls it when the plugin is applied to a project. -
tasks.register("greeting"): This is how we register a new task. Users can run it from the command line with./gradlew greeting. -
doLast {}: This block contains the code that runs when the task is executed.
Step 5: Understand the Plugin’s Behavior
To see the plugin in action, you can apply the plugin using its ID (org.example.greeting) in a plugins block:
plugins {
id("org.example.greeting")
}
After applying it, running the greeting task with ./gradlew greeting will produce the following output:
Hello from plugin 'org.example.greeting'
Step 6: What we will Build
This tutorial will guide you in building a powerful Slack Notification Gradle Plugin. This plugin will make it easy to automatically report your build results to a Slack channel.
The finished plugin will be able to:
-
Send a custom Slack message with a simple task (
sendTestSlackMessage). -
Automatically report build success or failure at the end of the build.
-
Integrate seamlessly with the build lifecycle using modern Gradle APIs like
FlowAction.
Step 7: Slack Client API Setup
To get started, you’ll need to set up the Slack API Client.
-
Get a Slack Account and Workspace:
-
Create a Slack Account.
-
Create a Slack Workspace where you have administrative privileges.
-
-
Create a Slack App:
-
Navigate to the Slack App creation page.
-
Select "Create An App" → "From Manifest" and accept the defaults to create a "Demo App".
-
-
Configure Permissions and Get Your Token:
-
Go to "OAuth & Permissions" in your app’s settings.
-
Under "Bot Token Scopes," click "Add an OAuth Scope" and select
chat:write. This gives your app permission to post messages. -
Select "Install App" to install it in your workspace.
-
A Bot User OAuth Token will be generated. It will start with
xoxb-. Be sure to save this token! It’s what we’ll use to authenticate our plugin’s API calls.
-
You’re all set! Now you have a working Gradle plugin project and all the tools you need to connect to Slack.
Next Step: Add an Extension >>