Skip to content
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

Undeclared build service deprecation when enabling stable configuration cache #1260

Closed
6 tasks done
ciscoo opened this issue Jul 22, 2022 · 2 comments · Fixed by #1262
Closed
6 tasks done

Undeclared build service deprecation when enabling stable configuration cache #1260

ciscoo opened this issue Jul 22, 2022 · 2 comments · Fixed by #1262
Labels

Comments

@ciscoo
Copy link

ciscoo commented Jul 22, 2022

If you are submitting a bug, please include the following:

  • summary of problem
  • gradle or maven version
  • spotless version
  • operating system and version
  • copy-paste your full Spotless configuration block(s), and a link to a public git repo that reproduces the problem if possible
  • copy-paste the full content of any console errors emitted by gradlew spotless[Apply/Check] --stacktrace

If you're just submitting a feature request or question, no need for the above.


Gradle 7.5 adds a new feature preview flag for stable configuration cache. When enabled, warnings appear due to Spotless' undeclared usage of SpotlessTaskService:

https://docs.gradle.org/7.5/release-notes.html#new-stable_configuration_cache-feature-flag

> Task :spotlessKotlinGradleApply UP-TO-DATE
Build service 'SpotlessTaskService' is being used by task ':spotlessKotlinGradleApply' without the corresponding declaration via 'Task#usesService'. This will fail with an error in Gradle 8.0. Declare the association between the task and the build service using 'Task#usesService'. Consult the upgrading guide for further information: https://docs.gradle.org/7.5/userguide/upgrading_version_7.html#undeclared_build_service_usage

> Task :cxf-codegen-gradle:spotlessJava
Build service 'SpotlessTaskService' is being used by task ':cxf-codegen-gradle:spotlessJava' without the corresponding declaration via 'Task#usesService'. This will fail with an error in Gradle 8.0. Declare the association between the task and the build service using 'Task#usesService'. Consult the upgrading guide for further information: https://docs.gradle.org/7.5/userguide/upgrading_version_7.html#undeclared_build_service_usage

> Task :cxf-codegen-gradle:spotlessJavaApply
Build service 'SpotlessTaskService' is being used by task ':cxf-codegen-gradle:spotlessJavaApply' without the corresponding declaration via 'Task#usesService'. This will fail with an error in Gradle 8.0. Declare the association between the task and the build service using 'Task#usesService'. Consult the upgrading guide for further information: https://docs.gradle.org/7.5/userguide/upgrading_version_7.html#undeclared_build_service_usage

> Task :cxf-codegen-gradle:spotlessKotlinGradleApply UP-TO-DATE
Build service 'SpotlessTaskService' is being used by task ':cxf-codegen-gradle:spotlessKotlinGradleApply' without the corresponding declaration via 'Task#usesService'. This will fail with an error in Gradle 8.0. Declare the association between the task and the build service using 'Task#usesService'. Consult the upgrading guide for further information: https://docs.gradle.org/7.5/userguide/upgrading_version_7.html#undeclared_build_service_usage

> Task :documentation:spotlessJavaApply UP-TO-DATE
Build service 'SpotlessTaskService' is being used by task ':documentation:spotlessJavaApply' without the corresponding declaration via 'Task#usesService'. This will fail with an error in Gradle 8.0. Declare the association between the task and the build service using 'Task#usesService'. Consult the upgrading guide for further information: https://docs.gradle.org/7.5/userguide/upgrading_version_7.html#undeclared_build_service_usage

> Task :documentation:spotlessKotlinGradleApply UP-TO-DATE
Build service 'SpotlessTaskService' is being used by task ':documentation:spotlessKotlinGradleApply' without the corresponding declaration via 'Task#usesService'. This will fail with an error in Gradle 8.0. Declare the association between the task and the build service using 'Task#usesService'. Consult the upgrading guide for further information: https://docs.gradle.org/7.5/userguide/upgrading_version_7.html#undeclared_build_service_usage
  • Gradle 7.5
  • Java 11 Temurin
  • Spotless 6.8.0
  • Linux Mint 20.3

You can see the warnings with a plugin I maintain. Specific Spotless configuration here: https://github.com/ciscoo/cxf-codegen-gradle/blob/master/buildSrc/src/main/kotlin/code-style-conventions.gradle.kts

@nedtwigg
Copy link
Member

Fixed in plugin-gradle 6.9.0.

@nedtwigg
Copy link
Member

I have complained a fair bit about the design of the configuration-cache

And I've also had to ask a lot of questions about how to correctly use BuildService, and there is a lot of ceremony involved.

For one thing, you can't just register "this class is my one-per-build BuildService", and then ask for that using the class as the key anywhere in Gradle. You instead have to imperatively register the service, and pass the handle to that registered service around.

BuildServiceRegistry buildServices = getProject().getGradle().getSharedServices();
taskService = buildServices.registerIfAbsent("SpotlessTaskService" + compositeBuildSuffix, SpotlessTaskService.class, spec -> {});

And, you can't pass it as just a regular field. Any task that uses it must declare a magically-generated "property getter", as such:

@Internal
public abstract Property<GitRatchetGradle> getGitRatchet();

The service then has to explicitly passed from Property to Property, which adds more boilerplate given that could be a global singleton injected based purely on GitRatchetGradle.class as the key.

Now, it turns out that is not enough boilerplate, you also have to call Task#usesService(Provider<BuildService>). Fine, so we'll add that. But if you've been passing the service between these magical Property<Blash> getProperty() gizmos, (btw Property extends Provider), you're about to hit another problem!

https://github.com/gradle/gradle/blob/262dcd02073f2b93ba1f88a863d0613d5f081d06/subprojects/core/src/main/java/org/gradle/api/services/internal/DefaultBuildServicesRegistry.java#L102-L105

A Provider<BuildService> is not good enough, it has to be a org.gradle.api.services.<INTERNAL!!!>.BuildServiceProvider, and only the very first call to register is one of those. As you pass that instance around to other tasks, those are just regular Provider, so you cannot use them for Task.usesService.

SOoooooo, we had to add even more boilerplate

so that we have the magical property getter to play nicely with configuration cache deserialization AND the internal.BuildServiceProvider to play nicely with Task.usesService.

I continue to love Gradle, and I continue to be super-duper flummoxed by the design of BuildServices and of ConfigurationCache. For each of these pieces, it would be good to be really clear about "what are the invariants", and "what is the key". IMO, for BuildService, the answers should be "the key is the class" and the invariant is "there is exactly one instance of this class throughout this build, and it will be created fresh on each build, and maybe we promise to never call this class from multiple threads (I don't care)". For "configuration cache", the invariant is "a task is being run and the exact same task was run earlier on this same JVM" and the key is "the task and the JVM". IMO. I'll do my best to make Spotless work worry-free with Gradle as it is designed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants