Learn about custom task types, create one, and add it to your plugin.

In this section, you’ll:

  • Understand what a custom task type is.

  • Create a SlackTask class that contains the logic for sending a message.

  • Add the necessary dependency for the Slack API client.

  • Register the custom task in your plugin’s apply method.

Step 0: Before you Begin

  1. You initialized your plugin in part 1.

  2. You added an extension to your plugin in part 2.

Step 1: About Custom Tasks

If your plugin introduces new functionality, you’ll typically define a custom task type. This allows you to encapsulate specific logic, like sending a Slack message, into a reusable and configurable Gradle task. We’ll then register this task in our plugin so users can execute it with a simple command.

Step 2: Create a Custom Task Type

Let’s create the class that will contain our Slack messaging logic.

Create a new file called `SlackTask.kt` in `src/main/kotlin/org/example/` and add the following code:
Create a new file called `SlackTask.groovy` in `src/main/groovy/org/example/` and add the following code:
plugin/src/main/kotlin/org/example/SlackTask.kt
package org.example

import com.slack.api.Slack
import com.slack.api.methods.request.chat.ChatPostMessageRequest

import org.gradle.api.DefaultTask
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import kotlin.text.isNotEmpty

/**
 * A custom Gradle task that sends a test message to a Slack channel.
 *
 * This task is useful for verifying Slack integration during build configuration.
 * It uses the Slack Web API and requires a bot token and a target channel.
 */
abstract class SlackTask : DefaultTask() {

    // The Slack bot token (usually starts with "xoxb-") used to authenticate the API request.
    @get:Input
    abstract val token: Property<String>

    // The Slack channel name or ID (e.g., "#builds" or "C12345678") where the message will be sent.
    @get:Input
    abstract val channel: Property<String>

    // The message content to be sent to the specified Slack channel.
    @get:Input
    abstract val message: Property<String>

    /**
     * Sends a message to Slack when the task is executed.
     * Useful for manual testing of Slack integration from the command line.
     */
    @TaskAction
    fun send() {
        // Initialize the Slack client and get the API methods interface
        val slack = Slack.getInstance()
        val methods = slack.methods(token.get())

        // Create a Slack message request
        val request = ChatPostMessageRequest.builder()
            .channel(channel.get())
            .text(message.get())
            .build()

        // Send the message via the Slack API and check for success
        val response = methods.chatPostMessage(request)
        if (response.isOk) {
            logger.lifecycle("Slack message sent successfully to channel ${channel.get()}")
        } else {
            // Fail the build if the Slack API response indicates an error
            logger.error("Failed to send Slack message: ${response.error}")
            throw RuntimeException("Slack message failed: ${response.error}")
        }
    }
}
plugin/src/main/groovy/org/example/SlackTask.groovy
package org.example

import com.slack.api.Slack
import com.slack.api.methods.request.chat.ChatPostMessageRequest

import org.gradle.api.DefaultTask
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction

/**
 * A custom Gradle task that sends a test message to a Slack channel.
 *
 * This task is useful for verifying Slack integration during build configuration.
 * It uses the Slack Web API and requires a bot token and a target channel.
 */
abstract class SlackTask extends DefaultTask {

    // The Slack bot token (usually starts with "xoxb-") used to authenticate the API request.
    @Input
    abstract Property<String> getToken()

    // The Slack channel name or ID (e.g., "#builds" or "C12345678") where the message will be sent.
    @Input
    abstract Property<String> getChannel()

    // The message content to be sent to the specified Slack channel.
    @Input
    abstract Property<String> getMessage()

    /**
     * Sends a message to Slack when the task is executed.
     * Useful for manual testing of Slack integration from the command line.
     */
    @TaskAction
    void send() {
        // Initialize the Slack client and get the API methods interface
        def slack = Slack.getInstance()
        def methods = slack.methods(token.get())

        // Create a Slack message request
        def request = ChatPostMessageRequest.builder()
                .channel(channel.get())
                .text(message.get())
                .build()

        // Send the message via the Slack API and check for success
        def response = methods.chatPostMessage(request)
        if (response.isOk) {
            logger.lifecycle("Slack message sent successfully to channel ${channel.get()}")
        } else {
            // Fail the build if the Slack API response indicates an error
            logger.error("Failed to send Slack message: ${response.error}")
            throw new RuntimeException("Slack message failed: ${response.error}")
        }
    }
}

This custom task type does a few important things:

  • It extends DefaultTask, which gives it all the basic functionality of a Gradle task.

  • It uses annotations like @Input and @TaskAction to clearly define its inputs and its primary action.

  • The @TaskAction method uses the Slack API client to post a message.

  • It includes robust error handling: if the Slack API call fails, the task will fail the build with a clear error message.

Step 3: Add the Slack API Dependency

Since our custom task uses the Slack API client, we need to add it as a dependency in our plugin’s build.gradle(.kts) file.

plugin/build.gradle.kts
dependencies {
    // Use the Java Slack Client APIs
    implementation("com.slack.api:slack-api-client:1.45.3")
}
plugin/build.gradle
dependencies {
    // Use the Java Slack Client APIs
    implementation("com.slack.api:slack-api-client:1.45.3")
}

Step 4: Register it in the Plugin

Now that we’ve defined our custom SlackTask class, we need to register it in our plugin’s apply method. This makes it available for users to run with a command like ./gradlew sendTestSlackMessage.

Open your plugin implementation file, `SlackPlugin.kt` (in `src/main/kotlin/org/example/`), and modify it to look like this:
Open your plugin implementation file, `SlackPlugin.groovy` (in `src/main/groovy/org/example/`), and modify it to look like this:
plugin/src/main/kotlin/org/example/SlackPlugin.kt
import org.gradle.api.tasks.TaskProvider

abstract class SlackPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        // Create the 'slack' extension so users can configure token, channel, and message
        val extension = project.extensions.create("slack", SlackExtension::class.java)

        // Register a task named 'sendTestSlackMessage' of type SlackTask
        val taskProvider: TaskProvider<SlackTask> = project.tasks.register("sendTestSlackMessage", SlackTask::class.java)

        // Configure the task using values from the extension
        taskProvider.configure {
            it.group = "notification" // Logical task grouping for help output
            it.description = "Sends a test message to Slack using the configured token and channel."

            // Bind extension values to the task's input properties
            it.token.set(extension.token)
            it.channel.set(extension.channel)
            it.message.set(extension.message)
        }
    }
}
plugin/src/main/groovy/org/example/SlackPlugin.groovy
import org.gradle.api.tasks.TaskProvider

abstract class SlackPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        // Create the 'slack' extension so users can configure token, channel, and message
        def extension = project.extensions.create('slack', SlackExtension)

        // Register a task named 'sendTestSlackMessage' of type SlackTask
        TaskProvider<SlackTask> taskProvider = project.tasks.register('sendTestSlackMessage', SlackTask)

        // Configure the task using values from the extension
        taskProvider.configure {
            // Logical task grouping for help output
            it.group = 'notification'
            // Sends a test message to Slack using the configured token and channel.
            it.description = 'Sends a test message to Slack using the configured token and channel.'

            // Bind extension values to the task's input properties
            it.token.set(extension.token)
            it.channel.set(extension.channel)
            it.message.set(extension.message)
        }
    }
}

This code:

  • Registers a new task named sendTestSlackMessage of our custom SlackTask type.

  • Configures the task with a group and description for better help output.

  • Binds the task’s properties (token, channel, message) to the corresponding properties in our plugin’s SlackExtension. This is how the user’s configuration is passed to the task.

Next Step: Write a Unit Test >>