CircleCI-Public / gradle-orb

Simplify common tasks for building and testing Java projects using Gradle on CircleCI using this orb.
https://circleci.com/orbs/registry/orb/circleci/gradle
MIT License
4 stars 11 forks source link

Cache JDKs auto provisioned by Gradle toolchains #17

Open jamesbassett opened 2 years ago

jamesbassett commented 2 years ago

Is your feature request related to a problem? Please describe. JDKs that are auto-provisioned by Gradle builds that use toolchains are not cached by the gradle orb.

Describe the solution you'd like I would like the gradle orb's with_cache command to cache auto-provisioned JDKs between builds.

Describe alternatives you've considered As a workaround you can manage this cache without the gradle orb (not ideal).

Additional context

Auto-provisioned JDKS live in .gradle/jdks.

I'm not sure how you would implement the cache key suffix (i.e. the cache_seed component) - the toolchain is likely configured in the build script (build.gradle.kts) but might be applied by a plugin.

Ideally you could work out what toolchain has been configured, but I can't see an easy way to do that.

The only thing I can think of is to run the following command and use the hash the output. Unfortunately it requires the toolchain to have been downloaded already (which defeats the purpose of the cache).

./gradlew -q -Porg.gradle.java.installations.auto-detect=false javaToolchains

 + Options
     | Auto-detection:     Disabled
     | Auto-download:      Enabled

 + Eclipse Temurin JDK 11.0.16+8
     | Location:           /Users/jim/.gradle/jdks/adoptium-11-aarch64-hotspot-mac/jdk-11.0.16+8/Contents/Home
     | Language Version:   11
     | Vendor:             Eclipse Temurin
     | Architecture:       aarch64
     | Is JDK:             true
     | Detected by:        Auto-provisioned by Gradle
jamesbassett commented 2 years ago

Running this will tell you what toolchain is requested (regardless of whether it's downloaded or not, because it turns off auto-provisioning and detection). But 🤮

./gradlew -Porg.gradle.java.installations.auto-download=false -Porg.gradle.java.installations.auto-detect=false check  

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':compileKotlin'.
> Could not resolve all dependencies for configuration ':kotlinCompilerPluginClasspathMain'.
   > Failed to calculate the value of task ':compileJava' property 'javaCompiler'.
      > No compatible toolchains found for request filter: {languageVersion=11, vendor=ADOPTIUM, implementation=vendor-specific} (auto-detect false, auto-download false)

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 410ms
Jaryt commented 2 years ago

This would be a great addition! I played around with this and couldn't find anything to specifically create a cache key for. However, I believe all toolchains are determined by build.gradle so it may just make sense to use that file for cache key. Not completely optimal as there may be changes to the file not associated with the toolchain, but might be the best there is for now.

ryanbourdais commented 1 year ago

Hi @jamesbassett I just started to look into this issue, but it seems that build.gradle was identified as the file that should be cached and that is currently the default for deps_checksum_file in the with_cache command. It appears to me that this issue is solved, but if it is not can you further explain the issue to me?

jamesbassett commented 1 year ago

Hi @ryanbourdais just to be clear this is totally independent of dependency caching (the provisioned toolchains live in a completely different directory .gradle/jdks and are not currently cached).

While it's quite possible that the toolchain is configured in a build.gradle.kts file like so:

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

it's also very possible that it has been applied by a Gradle plugin (binary or precompiled script) which means you can no longer compute the cache key from the build script.

So at the moment I'm not sure if this is solvable in a generic way - I was hoping somebody would have a clever idea 😉

As @Jaryt has suggested, caching the toolchain based on build.gradle.kts would probably work as expected most of the time, but I can think of a few downsides:

ryanbourdais commented 1 year ago

Hi @jamesbassett , I do see what you mean now. I think as @Jaryt suggested, caching build.gradle.kts is the best approach for the moment, but I'm going to leave this issue open and backlog it after PR #25 is merged in so hopefully we can get some more visibility on this issue