-
Notifications
You must be signed in to change notification settings - Fork 459
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Configuration cache, part 1 (play nice with others) #720
Conversation
… bumps our minimum gradle from 5.4 to 6.1
…ks aren't configured.
…ldFinished`, so that Spotless tasks don't interfere with config cache for other tasks.
By default build services are created when they are used and shut down once no task are using them. If you want your build service to be created at the beginning of the build and shut down at the end of the build there's some extra ceremony required:
|
Roger, thanks! How does Gradle know if a task needs a build service?We create our spotless/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/RegisterDependenciesTask.java Lines 86 to 91 in fa01f46
And then we use it both during configuration time and task execution. Because we use it at configuration time, we just pass the service as an argument to the tasks that need it, we don't inject it, but it is declared as an spotless/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTask.java Lines 89 to 98 in fa01f46
If the spec said "every BuildService which implements AutoCloseable will be closed when the build finishes" then I would know that we are okay. But it seems like Gradle is taking responsibility for knowing which tasks use the service, and I don't understand how I can signal to Gradle "I am using this object". Am I okay so long as I expose it with an How does Gradle persist build services across runs of the configuration cache?I don't understand how the |
1/ The task should have a 2/ Build services are per build. The configuration cache stores the name, type and parameters configured in the action. The type alone isn't enough. It is the same pattern as with artifact transforms or worker actions. |
Roger. So when tasks are restored from the configuration cache, a new That's a very cool, clever way to get properties from the buildscript execution into the In our case, and I would assume others, all we need is a build-lifetime singleton, which is a special case of the more general thing which you have built. You have provided the API we need, but fwiw, I would much prefer |
Indeed, the current build service API is about the basic building blocks. We will add conveniences over time. |
Hi Ned, |
@eskatos Am I right to think that to make this PR perfect, we'd need to ensure your earlier suggestions are all implemented? Specifically:
|
@jbduncan, yep 💯 |
@eskatos Great, thanks for confirming! I'm focusing my free open source time on another project, so I trust that Ned will get back to you at some point. |
The published version of Spotless already plays nicely with configuration cache so long as you don't cause the Spotless tasks to be configured, thanks to configuration avoidance. The cost of merging this PR is that our minimum Gradle bumps from
If anybody is in that position and wants to finish this PR, I'd be happy to merge it and bump our minimum Gradle. But the benefit is too low for this to make it to the top of my todo. I find configuration-cache to be most helpful for iterating on tests, and Spotless already lets that happen without conflict. |
I just found a case where configuring the spotless plugin is enough to trigger task creation thus configuration cache problems. The following snippet makes running plugins {
id("com.diffplug.spotless") version "<v>"
}
spotless {
java {
removeUnusedImports()
}
}
Simplified stacktrace:
|
Roger. Happy to merge the PR if anyone has time to finish it. I've been using configuration-cache for a few weeks and calling Spotless only with |
…chedGradle shared build service
in order to have Gradle call it's close() function when the build is finished
I just opened #937 which contains the changes described by @jbduncan in #720 (comment) The PR targets this one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks very much @eskatos. One last question for you (in the comments above) and then I'll merge and release.
|
||
@Override | ||
public void onFinish(FinishEvent finishEvent) { | ||
// NOOP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just want to confirm that we don't need to call close()
here? GitRatchet implements AutoCloseable
, so if Gradle is promising to call close()
then I guess we're good, but it's odd that there's also an onFinish()
which seems like it would get called at the same time as close()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OperationCompletionListener.onFinish
is called on each "task finish" event.
AutoCloseable.close
is called at the end of the build.
My understanding is that we are good.
getProject().getGradle().buildFinished(new Closure(null) { | ||
@SuppressFBWarnings("UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS") | ||
public Object doCall() { | ||
gitRatchet.close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is where we used to call close()
Thanks @eskatos for getting this over the hump. Will be released shortly. |
#720), it sucks that CircleCI doesn't automatically test merge commits in addition to merge tips.
Released in |
This PR establishes a few things:
5.6.1
doesn't interfere with configuration cache for other tasksGradle.buildFinished
at configure timeGradle.buildFinished
into aBuildService extends AutoCloseable
So now Spotless definitely doesn't interfere with configuration cache for other tasks. The cost is that we had to upgrade our required version from
5.4
to6.1
in order to getBuildService
.Unresolved question This assumes that a BuildService is created anew at the beginning of every build, and then destroyed at the end of every build. I think that might not be the case - it might be persistent across builds so long as a "configuration cache" is in-effect, in which case this PR is broken.