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
@TaskActionordoFirst/doLastcallbacks, the use ofProjectinstance is not allowed when the configuration cache is enabled. To run external processes, tasks should use an injectedExecOperationservice, which has the same API and can act as a drop-in replacement. The standard Java/Groovy/Kotlin process APIs, likejava.lang.ProcessBuildercan 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
ExecOperationsin 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?