Skip to content

Instantly share code, notes, and snippets.

@bamboo
Created August 19, 2020 21:48
Show Gist options
  • Save bamboo/b4c9678fc44aebc623fe849351ea95d3 to your computer and use it in GitHub Desktop.
Save bamboo/b4c9678fc44aebc623fe849351ea95d3 to your computer and use it in GitHub Desktop.
BuildService + projectsEvaluated callback example
import org.gradle.tooling.events.FinishEvent
import javax.inject.Inject
abstract class TraceService : BuildService<TraceService.Parameters>, org.gradle.tooling.events.OperationCompletionListener {
private
var projectsEvaluated = false
interface Parameters : BuildServiceParameters {
}
fun onProjectsEvaluated() {
println("onProjectsEvaluated()")
projectsEvaluated = true
}
override fun onFinish(event: FinishEvent) {
if (!projectsEvaluated) {
println("from the cache!")
}
println("onFinish($event)")
}
}
open class TraceServicePlugin @Inject constructor(
private val buildEventsListenerRegistry: BuildEventsListenerRegistry
) : Plugin<Settings> {
override fun apply(target: Settings) {
target.gradle.run {
val service = sharedServices.registerIfAbsent("traceService", TraceService::class) {
parameters {
// configure service here
}
}
buildEventsListenerRegistry.onTaskCompletion(service)
projectsEvaluated {
service.get().onProjectsEvaluated()
}
}
}
}
apply<TraceServicePlugin>()
@ThanosFisherman
Copy link

Hi. Your sample helped me a lot get a grasp on configuration-cache but I wonder Is there a way to determine whether a build failed or succeeded? I'm trying to migrate my BuildListener logic into a cached-compliant one and I would like to check whether the build suceeded or failed like I do with the buildFinished overriden method of BuildListener

    override fun buildFinished(result: BuildResult) {

        if (result.failure != null) {
            // build failure
        } else {
            // build success!
        }
    }

@bitspittle
Copy link

Thank you a ton for this gist. I came here after the Gradle docs dropped the ball and basically said, "If you needed our method to do X, well it's deprecated now. A migration example? Nah." (see also: https://docs.gradle.org/current/userguide/build_services.html#operation_listener)

@ThanosFisherman I'm here two months later, so you may have moved on, but the way I'm solving what you're trying to do is by using instance checks against FailureResult:

override fun onFinish(event: FinishEvent) {
    if (event.result is FailureResult) {
        // task failed
    }
    else {
        // task succeeded OR skipped (and possibly other states, I'm not sure)
    }
}

@ThanosFisherman
Copy link

ThanosFisherman commented Feb 14, 2022

@bitspittle Hey, I did move on by not supporting configuration cache in my plugins 😆

Your solution seems reasonable but I remember trying it in the past and somehow it wouldn't work for my case or perhaps I must have missed something important.

You might wanna check this thread here gradle/gradle#14860 (comment) Where I basically asked the same thing and received a similar response.

@bitspittle
Copy link

bitspittle commented Feb 14, 2022

That's a great thread, thanks for sharing. Lots of people are struggling with this :)

Luckily that approach is working for me so far. I am uncomfortable that I'm checking an interface match, since Gradle could possibly invent some different failure-ish type in the future and my code will silently stop working, which will be a pain to debug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment