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
Build finished event now deprecated #20151
Comments
Indeed, these are deprecated and planned to be removed. Alternatives have been documented but I can see that the Javadoc does not point to that information. Is your build emitting a deprecation message? Or are you seeing the deprecation only in the context of the IDE when editing the script? |
Gradle 7.5 will have more information on this deprecation and the alternatives that are configuration cache compatible. |
Thanks @ljacomet for the quick reply! I have my build treat deprecations as errors so that is why I see it. The IDE also shows the method as deprecated. Thanks for the pointer to the docs. I missed this while looking through the release notes. It will definitely help others to have a pointer to the alternatives in the Javadoc. |
@ljacomet The current docs (release notes) point to the Build Service feature with no further information. I checked the docs for 7.5 RC and nightly but did not find anything new regarding buildFinished. Will there be other alternatives in 7.5 as you mentioned above? |
@ljacomet: Still I do not get the documentation, even with the link you provided. Your link points to Build finished events -> configuration cache chapter -> build services. Does it mean we have to implement a custom build service to solve the issue? |
The deprecation in 7.4 is soft: only the In the context of using the configuration cache you can use an cc @gradle/bt-configuration-cache |
@eskatos and @ljacomet Thanks guys for following up on this issue. In general, I highly recommend that Gradle does not deprecate (strongly or softly) any major feature such as the build status callbacks without prior warning and a reasonable replacement that is ready for use at the time of the deprecation (not at the time of removal). |
Can you link directly to the documented alternatives? The link you provided isn't very clear. I eventually end up at the bottom of this page https://docs.gradle.org/current/userguide/build_services.html#operation_listener, but the description isn't clear.
What is that supposed to mean? What's a |
Okay I think I've figured it out. Here's a 'minimal' example you can copy into a // build.gradle.kts
abstract class BuildListenerService :
BuildService<BuildListenerService.Params>,
org.gradle.tooling.events.OperationCompletionListener {
interface Params : BuildServiceParameters
override fun onFinish(event: org.gradle.tooling.events.FinishEvent) {
println("BuildListenerService got event $event")
}
}
val buildServiceListener = gradle.sharedServices.registerIfAbsent("buildServiceListener", BuildListenerService::class.java) { }
abstract class Services @Inject constructor(
val buildEventsListenerRegistry: BuildEventsListenerRegistry
)
val services = objects.newInstance(Services::class)
services.buildEventsListenerRegistry.onTaskCompletion(buildServiceListener) In the logs I can see the printed message
|
@aSemy Thank you! I have tried this too, but @eskatos Can you add something like the above for Gradle 7.6 or explain if there is a different way to notify the build service that the entire build has completed? |
I just added this to my Kotlin script and it seems to be working ok. Pleased to hear of any improvements.
|
Respectfully, what the heck? Speaking to those who thought that deprecating I'm hoping that |
Hi everyone, this public specification describes how we're planning to improve the situation in 8.1. |
Implemented in #17659 |
@bamboo Is there any documentation with examples showing how to use the new APIs to solve the problem this ticket was for? |
https://docs.gradle.org/current/userguide/dataflow_actions.html It works, but the concepts you have to understand are quite a handful for such a simple task. I wonder if one could develop some sort of convenience method that is close to the original buildFinished listener. |
@ingokegel I've read that already, but it's so severely constricted it seems to be written for Twitter in mind. I know no more after reading it than I knew before. |
@asarkar It is indeed very complicated. On the
Looking at the code it is very difficult to understand what is happening and I really wonder if all of this is necessary just to work with the build cache. |
Hello! |
Hi, I was trying to replace the usage of Show potential replacement for code in nix-idea ...import org.jetbrains.intellij.tasks.RunIdeBase
// I haven't found a way to access services (like FlowScope) from script plugins,
// so I created this nested plugin class.
apply<DelegatePlugin>()
abstract class DelegatePlugin : Plugin<Project> {
@get:Inject
protected abstract val flowScope: FlowScope
@get:Inject
protected abstract val flowProviders: FlowProviders
override fun apply(target: Project) {
val jbr = target.providers.of(JbrSource::class.java) {
parameters.path.set(target.file("jbr/bin/java"))
}.orNull
if (jbr == null) {
flowScope.always(JbrGuidance::class) {
parameters.project.set(target)
parameters.buildResult.set(flowProviders.buildWorkResult)
}
} else {
target.tasks.withType<RunIdeBase> {
projectExecutable.set(jbr)
}
}
}
}
abstract class JbrSource : ValueSource<String?, JbrSource.Parameters> {
interface Parameters : ValueSourceParameters {
@get:Input
val path: Property<File>
}
override fun obtain(): String? {
return parameters.path.get().takeIf { it.exists() }?.toString()
}
}
abstract class JbrGuidance : FlowAction<JbrGuidance.Parameters> {
private val regex = Regex("""\.gradle/.*/jbr/.*/java\b""")
interface Parameters : FlowParameters {
@get:Input
val project: Property<Project>
@get:Input // Unused, but tells Gradle that this action shall be executed at the end of the build
val buildResult: Property<BuildWorkResult>
}
override fun execute(parameters: Parameters) {
//val logger = org.slf4j.LoggerFactory.getLogger("jbr-guidance")
val project = parameters.project.get()
val logger = project.logger
val taskGraph = project.gradle.taskGraph
for (task in taskGraph.allTasks) {
if (task.project == project && task is RunIdeBase &&
task.state.failure?.cause?.message?.contains(regex) == true
) {
logger.error("""
|
|! Info for users on NixOS:
|!
|! The JetBrains Runtime (JBR) downloaded by Gradle is not compatible with NixOS.
|! You may run the ‘:jbr’ task to configure the runtime of <nixpkgs> instead.
|! Alternatively, you may run the following command within the project directory.
|!
|! nix-build '<nixpkgs>' -A jetbrains.jdk -o jbr
|!
|! This will create a symlink to the package jetbrains.jdk of nixpkgs at
|! ${'$'}projectDir/jbr, which is automatically detected by future builds.
""".trimMargin())
break
}
}
}
}
|
Is there any example project showing how to replace
to the working solution with all project dirs/paths and files that are needed provided? |
@samoylenkodmitry there's a working example in the Gradle repo which is used to generate the docs. Suggestion: You don't necessarily need the full ceremony of a Settings plugin, you can copy the body of |
Thanks to @SimonCJacobs's demo and serviceOf() in Kotlin DSL mentioned by @TWiStErRob, I made it after half a day's spike. To save time, here is my full code snippets to print the time-consuming statistics of each task:
Hope it would be useful for the new beginers who is looking for the gradle hooks alternative on the latest version. |
Sorry for the off-topic, but would like to point out some potential pitfalls related to @Fermiz's code. I recommend continuing discussion in Gradle Community Slack. For "build-end" detection it's probably better to use the For example in AGPWe have Also with For exampleIn a multi-module project, Both of these could result in mis-information from the stats, missing long tasks from the table; or if the code is not printing, duplicate processing of potentially wrong data. |
@Fermiz, your
The only limitation compared to the Note that a build may still fail, even if there is not a single failing task. For example, the serialization of task inputs may fail when the configuration cache is enabled. I don't know why Gradle doesn't just provide a method similar to |
Starting in Gradle 7.4, both the
Gradle.buildFinished
andBuildListener.buildFinished
are deprecated. Apparently, it was not possible to get these methods to work with the configuration caching feature. The deprecation message does not list an alternative mechanism for being called when a build completes. In addition to this deprecation breaking one of my plugins, it seems like a serious regression to remove the ability to receive such a fundamental event as the completion of the build. Perhaps I am missing some other mechanism for receiving this event.Expected Behavior
Ability to register an event handler for build completion.
Current Behavior
The buildFinished event has been deprecated with no apparent replacement.
Context
Deprecation in Gradle 7.4.
The text was updated successfully, but these errors were encountered: