Hi,
coming from non parallel task execution, before configuration cache was a thing, I got some tasks which need some external stuff running (which I do spawn and shutdown via dependsOn + finalizers), that worked fine so far and it does so with org.gradle.workers.max=1, which may be a lucky coincidence though.
Trying to make use of the parallel nature for the rest of my build, I thought using a shared build service with maximum parallel usage would be sufficient for those who need it which does work - however, my build prerequisites and finalizers are executed in a different order now, which is obviously fatal for the build itself, because that external stuff does need that order (compose container setup with conflicting services and ports which I stubbed out for that example).
As an example GitHub - tkrah/spring-sec-14911 at buildservice · GitHub you can run:
./gradlew integrationTest
With 1 worker it will have that order:
> Task :composeUp
composeUp
> Task :docker1:runTest
runTest
> Task :composeDown
composeDown
> Task :e2eComposeUp
e2eComposeUp
> Task :docker2:e2eRunTest
e2eRunTest
> Task :e2eComposeDown
e2eComposeDown
With more than one worker however (change the worker property in the project prop file) the order does change to:
> Task :composeUp
composeUp
> Task :e2eComposeUp
e2eComposeUp
> Task :docker1:runTest
runTest
> Task :docker2:e2eRunTest
e2eRunTest
> Task :composeDown
composeDown
> Task :e2eComposeDown
e2eComposeDown
I am wrapping my head around the lifecycle, if I use the –task-graph argument I get:
> ./gradlew integrationTest --task-graph
Reusing configuration cache.
Task graph printing is an incubating feature.
Tasks graph for: integrationTest
+--- :docker1:integrationTest (org.gradle.api.DefaultTask)
| +--- :composeUp (org.gradle.api.tasks.Exec)
| | \--- :composeDown (org.gradle.api.tasks.Exec, finalizer)
| \--- :docker1:runTest (org.gradle.api.tasks.Exec)
\--- :docker2:integrationTest (org.gradle.api.DefaultTask)
+--- :e2eComposeUp (org.gradle.api.tasks.Exec)
| \--- :e2eComposeDown (org.gradle.api.tasks.Exec, finalizer)
\--- :docker2:e2eRunTest (org.gradle.api.tasks.Exec)
So far so good but even with a build service with max usage = 1 that will not run in my desired order anymore.
So - how would I solve that problem so that I can make sure
a) some tasks are not run in parallel at all and
b) the pre-requisites are only run just before the actual task which needs it and finalizers are executed immediately and not deferred?
From an isolated view I can see why Gradle does that because it does not know that those tasks may conflict externally and just spawn those one after another although serially - while they do not run in parallel anymore, they still will fail because of external conflicts (although I am wondering why I get my expected order with workers = 1).
Suggestions how to fix the current structure and / or rewrite it with some other feature of Gradle to get that running with workers > 1?
Thanks.