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

Reply via email to