I’ve got a custom Gradle task like this:
tasks.register("myTask") {
doLast {
exec { commandLine("sh", "-c", "myscript.sh") }
exec { commandLine("sh", "-c", "myscript2.sh") }
}
}
When I run it, I get this warning:
The Project.exec(Action) method has been deprecated. This is scheduled to be removed in Gradle 9.0. Use ExecOperations.exec(Action) or ProviderFactory.exec(Action) instead. Consult the upgrading guide for further information: Upgrading your build from Gradle 8.x to the latest
The guide there is super unhelpful.
At execution time, for example in
@TaskAction
ordoFirst
/doLast
callbacks, the use ofProject
instance is not allowed when the configuration cache is enabled. To run external processes, tasks should use an injectedExecOperation
service, which has the same API and can act as a drop-in replacement. The standard Java/Groovy/Kotlin process APIs, likejava.lang.ProcessBuilder
can be used as well.
I have no idea what any of that means.
The ExecOperation
page gives this, uh, rather verbose code example.
With some ceremony, it is possible to use
ExecOperations
in an ad-hoc task defined in a build script:interface InjectedExecOps { @get:Inject val execOps: ExecOperations } tasks.register("myAdHocExecOperationsTask") { val injected = project.objects.newInstance<InjectedExecOps>() doLast { injected.execOps.exec { commandLine("ls", "-la") } } }
Is that what the Gradle team recommends that I do to run a quickie one-line shell script?
It seems like not, because right underneath the code sample, there’s a “tip.”
Tip
This is a good time to consider extracting the ad-hoc task into a proper class.
Would using a “proper class” be better, somehow? The example in the docs looks like this:
abstract class MyExecOperationsTask
@Inject constructor(private var execOperations: ExecOperations) : DefaultTask() {
@TaskAction
fun doTaskAction() {
execOperations.exec {
commandLine("ls", "-la")
}
}
}
tasks.register("myInjectedExecOperationsTask", MyExecOperationsTask::class) {}
It seems like Gradle is saying that it was wrong of me to write exec { commandLine("myscript.sh") }
, but that instead I ought to have defined a “proper class” to do it instead.
But, on the other hand, the docs seem to be claiming that the new thing is a “drop-in replacement.” This is not a drop-in replacement; this is replacing a one-liner with an injected AbstractSingletonProxyFactoryBean
.
Is there a drop-in replacement available to me? Do I have replace all of my exec
calls with these weird injections?