Passing parameter to custom Gradle task - gradle

I've written simple custom Gradle task that extends DefaultTask and does some action and I would like to pass it some parameter(s) using command line. At the bottom is code for adding task to list of available tasks and "implementation" of the task.
Now, when I execute: ./gradlew customTask -PcustomParam="value" how can I retrieve customParam value in doAction method?
project.tasks.create("customTask", CustomTask::class.java
open class CustomTask : DefaultTask() {
#TaskAction
fun doAction() {
// retrieve passed parameter
}
}

if (project.hasProperty('customParam')) {
println project.property('customParam')
}
#see project.property(String name)

Related

How to incorporate command-line arguments in a custom Gradle Task?

I'm working on building a Gradle plugin that contains a single task which will combine two input files (the filename of one is constructed from command-line input) into one output file. I have followed this DZone article to set up my task and plugin classes. When I run the task, I see the log statement containing the command-line input, but the the plugin code to configure the task gets a null value for the input. How can I fix this? Example code below.
class FooPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.tasks.register("foo", FooTask) {
if (it.hasProperty("bar") {
it.baseFile.convention(project.layout.projectDirectory.file("my${bar}.txt")
}
}
}
}
#CompileSTatic
abstract class FooTask extends DefaultTask {
#Input
String bar
#InputFile
abstract RegularFileProperty getBarFile()
#Option(option = "bar", description = "Does bar-ish things")
void setBar(bar) {
println "Setting bar variable from command-line argument $bar"
this.bar = bar
}
#TaskAction
void doFoo() {
// task logic using the bar variable
}
}

How to pass #Input String in a task in buildSrc

This custom plugin exists in gradle's buildSrc/:
abstract class MyTask : DefaultTask() {
#get:Input
abstract val buildDir: Property<String>
#TaskAction
fun someTask() {
// do stuff
}
}
class DevelopmentPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.run {
register("myTask", MyTask::class.java) {
inputs.property("buildDir", project.buildDir)
println(inputs.getProperties())
}
}
}
}
and by running the task with e.g. $ ./gradlew myTask fails with:
Could not determine the dependencies of task ':myTask'.
> Cannot query the value of task ':myTask' property 'rootDir' because it has no value available.
Also the prinln outputs {buildDir=null} meaning that the inputs.property("buildDir", project.buildDir) has failed.
How to pass the project.buildDir value from the Plugin in the task?
Using project.buildDir directly from inside the task is not an acceptable answer due to Gradle's incubating build-cache functionality.
Firstly, there is a class type issue which is not visible in Gradle.
buildDir is of type File while the property is String.
So "${project.buildDir}" should be used.
Secondly, since the property is abstract val it can directly be accessed in the closure. Therefore it can be set with:
// instead of:
inputs.property("buildDir", "${project.buildDir}")
// just this:
buildDir.set("${project.buildDir}")

Can a Gradle task return a value?

I'm writting a custom Gradle Task. Assuming the following is valid:
class MyTask extends DefaultTask {
#TaskAction
def doAction() {
return "my task""
}
}
I'm might be missing something obvious, but how do I get the value back when calling the task?

Private method visibility confusion

I am confused with Groovy method visibility in the context of my Gradle build.
For some tests in my project, I have to first start a server.
For this I created a custom task class that extends Gradle's Test like so:
class TestWithServer extends Test {
TestWithServer() {
super()
beforeTest {
startServer()
}
}
private void startServer() {
println('placeholder')
}
}
But if I try to run such a task, I get an error:
Could not find method startServer() for arguments [] on task ':testWithServer' of type TestWithServer.
I found that when I change the visibility of startServer() to the default (public), the task runs fine.
How come I can't use the private method from within its own class?
It is not the same class, because Gradle adds some magic to the task types. Just add println this.class into the beforeTest closure to see the name of the actual class (something like TestWithServer_Decorated). This additional magic also explains why the error message contains the task name and how the class knows about being a task (type) at all. Since the decorated class is a subclass of your class you can use the protected modifier to encapsulate your method.

Gradle Custom Task Configuration

I'm working on a Gradle plugin that has a Custom Task with two member variables that I would like to initialize using an extension class. I am extending the plugin class as follows:
class CustomPlugin implements Plugin<Project> {
#Override void apply(Project project) {
def extension = project.extensions.create("Custom", CustomExtension)
project.task("doTask", type: CustomTask, {
group = "Awesome"
description = "Runs a custom routine"
filePath = extension.filePath
name = extension.name
})
}
}
Is this the proper way to initialize a Task that extends DefaultTask? I'm trying to understand if initialization is done in CustomPlugin or if within the CustomTask one would use:
#TaskAction void removeUnusedResources() {
String filePath = project.Custom.lintXmlFilePath
String name = project.Custom.ignoreResFiles
// Proceed with the task action
}
Only the second approach seems to work for me. One common pattern I am noticing in other plugins is that tasks tend to be defined within the plugin using project.task("taskName") << { // task actions here} instead of creating a separate class that extends DefaultTask. What is the right convention and where can I find more information?

Resources