Extensions on tasks

Suppose I have a task of an existing third-party type for which you can’t supply all the inputs right away, but you can with an extension. Something like

Third-party:

interface MyTaskExtension {
    val flag: Property<Boolean>
}

abstract class MyTask : DefaultTask() {
    abstract val parameter: Property<String>
}

tasks.register<MyTask>("myTask")

Somewhere in my code:

tasks.named<MyTask>("myTask").configure {
    val extension = extensions.create<MyTaskExtension>("myExtension")
}

Elsewhere in my code:

tasks.named<MyTask>("myTask").configure {
    parameter.set(the<MyTaskExtension>().flag.map { if (it) "foo" else "bar" })
}

Suppose that I have applied the third party plugin, and both of my custom configuration blocks have also been applied. Is there any guarantee that the first configuration block that defines the extension will be applied before the second configuration block, or will the second configuration block need to defer the extension lookup until the task is running? (Is that even configuration cache compatible?)

You should definitely not change the configuration at execution time. Even without configuration cache this is very bad and flaky at best.

The order of the blocks is the order you registered them. So your logic should make sure your first block is executed first, then you are fine. Or you try to drag the two together to one block if you can.

I meant the second block being something like

tasks.named<MyTask>("myTask").configure {
    parameter.set(project.providers.provider {
       the<MyTaskExtension>().flag.map { if (it) "foo" else "bar" }
    })
}

Would that work in case the second block somehow gets added before the first, or would that be a bit redundant?

Maybe, I’m not sure. But maybe you should just register the extension if it is not registered yet.