Skip to content

xvik/learn-gradle-configuration-cache

Repository files navigation

Learn gradle configuration cache by examples

License CI

Repository contains various samples to show the behavior of Gradle configuration cache. You can use it as a learning playground: each sample could be modified and re-run (with test).

Useful links:

TLDR;

  • You can do whatever you want at configuration time. You are limited at execution time
    • Provider and ValueSource are common workarounds for execution time
    • Objects (custom objects, tasks, etc.) field values are preserved (values assigned at configuration time!)
  • You can't rely on objects uniqueness because configurations are serialized, which means the same object, used at different places would be deserialized into different instances
    • Build services are the only way for uniqueness
    • Build services could also replace TaskExecutionListener (not compatible with configuration cache)
    • The first run with the enabled configuration cache is not the same as the usual Gradle run (objects serialization side effects already present)!
  • Method calls (at execution time) are not cached, but provider values are
  • Task constructor is in configuration scope, so the project is accessible!
  • Simple configuration cache usage tips are not covered, read gradle guide

Samples

  1. Simple demo shows what plugin parts are not executed under cache
  2. Shared objects shows configuration serialization side effects
  3. Build services shows how to communicate between tasks under cache and listen for tasks execution
  4. Method calls, providers shows provider behavior at execution time
  5. Task constructor shows that task constructor could be used to reference all required project-related properties under configuration time

For each sample a test output is present in readme. But you can run tests yourself (with modifications or other gradle versions).

Implementation details

Requires java 17 (multiline strings used to simplify tests).

Each sample is in its own package. Relative test lay out in the same package.

Tests use Gradle TestKit. To demonstrate configuration cache, the same build must be run multiple times:

  • First with configuration cache enabled (--configuration-cache) to create cache record
  • The second run shows behavior under the configuration cache
  • Some tests use a third execution to show cache invalidation.

Each test run creates a temp directory as a project root (@TempDir File projectDir). Build file created inside this directory.

Example run:

BuildResult result = GradleRunner.create()
        .withProjectDir(projectDir)
        .withArguments(List.of("myTask", "--configuration-cache"))
        .withPluginClasspath()
        .forwardOutput()
        .build();

// validation
result.getOutput().contains("something");

All tests end with KitTest because usually gradle plugin projects also contain ProjectBuilder-based tests. There are no such tests, but convention preserved.

AssertJ used because of its great errors output on strings comparison.

Configuration cache errors

Just in case, when there is a configuration cache problem, gradle would idicate it like this:

> Task :sample5Task
Task executed: junit12045893691932608949

1 problem was found storing the configuration cache.
- Task `:sample5Task` of type `ru.vyarus.gradle.plugin.sample5.Sample5Task`: invocation of 'Task.project' at execution time is unsupported.
  See https://docs.gradle.org/8.13/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution

During the real plugin project migration, the target is to aliminate all such errors.

Note that different errors might appear in different cases: all plugin execution "branches" must be checked for configuration cache compatibility (gradle will not print all warnings at once - only for actually executed code).

About

Learn gradle configuration cache by example (playground)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages