On 10/10/2011, at 9:22 PM, Peter Niederwieser wrote:
> I've had the need for "wiring variations" on several occasions, but typically
> not limited to a single task.
I'm curious, do you have some example use cases?
> Therefore I'd like to propose a more general
> concept. Let's call it "true lifecycle tasks". :-)
>
> A true lifecycle task behaves like a normal task, with three differences:
>
> 1. It can't have any actions
> 2. It doesn't show up in the command line output
> 3. Its configuration block(s) are only evaluated once Gradle has determined
> that the task is going to be executed
>
> Note that the configuration blocks can contain any configuration, not
> necessarily related to the task itself. They can also add new task
> dependencies between arbitrary tasks.
>
> 'integTestAll' now looks as follows (syntax is just exemplary):
>
> integTestAll(type: LifecycleTask) {
> jettyStop.dependsOn integTest
> integTest.dependsOn jettyStart
> }
>
> (It would be nice to have a more succinct syntax for task chains, e.g.
> 'jettyStop.dependsOn(integTest).dependsOn(jettyStart)'.)
>
> Since those task dependencies are introduced conditionally, 'jettyStop' on
> its own doesn't depend on 'integTest'. This makes a lot of sense, both
> conceptually and in practice. I suppose your solution would have achieved
> the same.
>
> But true lifecycle tasks can do more. If we use them for tasks like 'check'
> and 'build', those tasks no longer appear in the command line output (which
> is good).
Interesting. Why do you think that is good?
I would have thought we'd want to go in the other direction: ie show less and
less of the detail (ie worker tasks) and leave just the high-level stuff (ie
lifecycle tasks). For example, I'd rather see:
check UP-TO-DATE
instead of
compileJava UP-TO-DATE
compileGroovy UP-TO-DATE
processResources UP-TO-DATE
compileTestJava UP-TO-DATE
compileTestGroovy UP-TO-DATE
processTestResources UP-TO-DATE
test UP-TO-DATE
checkstyleMain UP-TO-DATE
codenarcMain UP-TO-DATE
checkstyleTest UP-TO-DATE
checkstyleMain UP-TO-DATE
(lifecycle tasks classes, testClasses and check removed)
> True lifecycle tasks are also a great fit for modeling different
> build types:
>
> task ciBuild(type: LifecycleTask) {
> dependsOn(build)
> check.dependsOn(ciOnlyChecks)
> }
>
> 'ciOnlyChecks' could even be introduced conditionally within the 'ciBuild'
> configuration block.
>
> Imagine 'ciBuild' is added by a plugin. Then builds can easily add CI build
> specific behavior like so:
>
> ciBuild { ... }
>
> Or potentially for multiple build types at once:
>
> configure(ciBuild, releaseBuild) { ... }
>
> I'm sure there are more applications of this concept, but these are the ones
> I can think of right now. What do you think?
We certainly want to have some way to conditionally wire up and configure an
arbitrary set of tasks when a given task is to be executed. I'm not sold on
using the configure block of a particular type of task. Or to bolting it
together with 2 other behaviours.
I think we should offer conditional configuration as a cross-cutting capability
for all tasks, ideally as the default behaviour. It's a separate question as to
whether we offer some convenience LifecycleTask which does some other stuff.
--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com