I have a working Gradle plugin with an extension implemented using Kotlin. And I want to improve it by adding "nested" configuration. How should I extend my extension class for this?
This is how I configure my plugin in the build.gradle.kts
file in the project which uses the plugin.
myName {
nexusServer.set("https://some-url")
nexusUser.set("some-user")
nexusPass.set("some-password-taken-from-env-variable-provider")
nexusRepository.set("some repository")
}
Instead of this I want to have the following "nested" configuration.
myName {
nexus {
server.set("https://some-url")
user.set("some-user")
pass.set("some-password-taken-from-env-variable-provider")
repository.set("some repository")
}
}
For this I want to do something like explained in the following document Developing Custom Gradle Types. However, the examples are in Java and for the task but not the plugin extension. I do not know how to convert it to Kotlin and plugin extension.
Here is what I already have and want to update.
The extension class.
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
abstract class MyPluginExtension {
abstract val nexusServer: Property<String>
abstract val nexusUser: Property<String>
abstract val nexusPass: Property<String>
abstract val nexusRepository: Property<String>
}
The plugin class.
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.register
class MyPlugin : Plugin<Project> {
override fun apply(target: Project) {
val extension = target.extensions.create("myName", MyPluginExtension::class.java)
with(target.tasks) {
register<MyTask>("taskName") {
group = "myGroup"
description = "Do something"
nexusServer.set(extension.nexusServer)
nexusUser.set(extension.nexusUser)
nexusPass.set(extension.nexusPass)
nexusRepository.set(extension.nexusRepository)
}
}
}
}
To define a nested configuration inside an extension we add property and method to the extension.
First, we define property with the Nested
attribute.
@get:Nested
abstract val appCenter: AppCenter
Second, we define a method with the same name as the property.
fun appCenter(action: Action<AppCenter>) = action.execute(appCenter)
Here is the complete example.
import org.gradle.api.Action
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Nested
abstract class MyExtension {
@get:Nested
abstract val appCenter: AppCenter
fun appCenter(action: Action<AppCenter>) = action.execute(appCenter)
abstract class AppCenter {
abstract val token: Property<String>
abstract val owner: Property<String>
}
}
Here is the usage of the configuration.
extName {
appCenter {
token = providers.environmentVariable("VAR1")
owner = providers.environmentVariable("VAR2")
}
}