{"id":30230197,"url":"https://github.com/xvik/learn-gradle-configuration-cache","last_synced_at":"2026-04-16T11:03:14.250Z","repository":{"id":308144260,"uuid":"1031767038","full_name":"xvik/learn-gradle-configuration-cache","owner":"xvik","description":"Learn gradle configuration cache by example (playground)","archived":false,"fork":false,"pushed_at":"2025-12-01T07:21:12.000Z","size":184,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-12-03T18:43:26.478Z","etag":null,"topics":["configuration-cache","gradle","gradle-plugin-development"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xvik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-04T09:51:13.000Z","updated_at":"2025-12-01T07:21:15.000Z","dependencies_parsed_at":"2025-09-06T11:14:55.860Z","dependency_job_id":"feefe914-f8e3-4ffb-a3ec-17afa8893cbd","html_url":"https://github.com/xvik/learn-gradle-configuration-cache","commit_stats":null,"previous_names":["xvik/learn-gradle-configuration-cache"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/xvik/learn-gradle-configuration-cache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvik%2Flearn-gradle-configuration-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvik%2Flearn-gradle-configuration-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvik%2Flearn-gradle-configuration-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvik%2Flearn-gradle-configuration-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xvik","download_url":"https://codeload.github.com/xvik/learn-gradle-configuration-cache/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xvik%2Flearn-gradle-configuration-cache/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31882886,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T09:23:21.276Z","status":"ssl_error","status_checked_at":"2026-04-16T09:23:15.028Z","response_time":69,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration-cache","gradle","gradle-plugin-development"],"created_at":"2025-08-14T22:39:22.710Z","updated_at":"2026-04-16T11:03:14.245Z","avatar_url":"https://github.com/xvik.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Learn gradle configuration cache by examples\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://www.opensource.org/licenses/MIT)\n[![CI](https://github.com/xvik/learn-gradle-configuration-cache/actions/workflows/CI.yml/badge.svg)](https://github.com/xvik/learn-gradle-configuration-cache/actions/workflows/CI.yml)\n\nRepository contains various samples to show the behavior of Gradle configuration cache.\nYou can use it as a learning playground: each sample could be modified and re-run (with test). \n\nUseful links:\n\n* [General description](https://docs.gradle.org/current/userguide/configuration_cache.html)\n* [**Configuration cache usage guide**](https://docs.gradle.org/current/userguide/configuration_cache_requirements.html) \n* [Build services](https://docs.gradle.org/current/userguide/build_services.html)\n* [Gradle services](https://docs.gradle.org/current/userguide/service_injection.html#service_injection)\n\n\nBased on this repo, the article was written (in two parts):\n\n* [Gradle configuration cache by example. Part 1: behaviour](https://blog.vyarus.ru/gradle-configuration-cache-by-example-part-1-behavior)\n* [Gradle configuration cache by example. Part 2: problems](https://blog.vyarus.ru/gradle-configuration-cache-by-example-part-2-problems)\n\nРусская доработанная версия (Habr):\n\n* [Gradle configuration cache на примерах. Часть 1: поведение](https://habr.com/ru/articles/965126/)\n* [Gradle configuration cache на примерах. Часть 2: практика](https://habr.com/ru/articles/967242/)\n\n## TL;DR\n\n* You can do whatever you want at *configuration* time. You are limited at *execution* time\n    - `Provider` and `ValueSource` are common workarounds for execution time\n    - Objects (custom objects, tasks, etc.) field values are preserved (values assigned at configuration time!) \n* You can't rely on objects uniqueness because configurations are serialized, which means the same object,\nused at different places would be deserialized into different instances\n    - Build services are the only way for uniqueness\n    - Build services could also replace TaskExecutionListener (not compatible with configuration cache)\n    - The first run with the enabled configuration cache is **not the same** as the usual Gradle run (objects\n      serialization side effects already present)!\n* Method calls (at execution time) are not cached, but provider values are\n* Task constructor is in configuration scope, so the project is accessible!\n* Simple configuration cache usage tips are not covered, read [gradle guide](https://docs.gradle.org/current/userguide/configuration_cache_requirements.html)\n\n## Samples\n\n1. [Simple demo](src/main/java/ru/vyarus/gradle/plugin/sample1/) shows what plugin parts are not executed under cache\n2. [Shared objects](src/main/java/ru/vyarus/gradle/plugin/sample2/) shows configuration serialization side effects\n3. [Build services](src/main/java/ru/vyarus/gradle/plugin/sample3/) shows how to communicate between tasks under cache and listen for tasks execution\n4. [Method calls, providers](src/main/java/ru/vyarus/gradle/plugin/sample4/) shows provider behavior at execution time \n5. [Task constructor](src/main/java/ru/vyarus/gradle/plugin/sample5/) shows that task constructor could be used to reference all required \nproject-related properties under configuration time \n6. [Build service runtime access](src/main/java/ru/vyarus/gradle/plugin/sample6/) shows that build service\ncan't remember its state (changed during configuration), but gradle could cache service access\npoints, so there is (probably) no need to maintain the correct state.\n7. [Build service parameter](src/main/java/ru/vyarus/gradle/plugin/sample7/) state, collected under configuration phase\ncould be stored in the build service parameter (but with a caveat)\n8. [Listen cached task](src/main/java/ru/vyarus/gradle/plugin/sample8/) might be used together with the configuration cache,\nbut this might lead to not executed `doFirst`/`doLast` blocks (on which you could rely on). Service could workaround this\nlimitation.\n9. [Multi module projects](src/main/java/ru/vyarus/gradle/plugin/sample9/) pays attention to multi-module\nprojects side effects (which must be also counted)\n10. [Real life case](src/main/java/ru/vyarus/gradle/plugin/sample10/) shows how to collect tasks state in\nvalue objects and use it in build service task listener\n\nFor each sample a test output is present in readme. But you can run tests yourself \n(with modifications or other gradle versions).\n\n## Fail cases\n\n1. [Project usage in task](src/main/java/ru/vyarus/gradle/plugin/fails/fail1/) shows that project can't be used at runtime\n2. [Project usage in plugin](src/main/java/ru/vyarus/gradle/plugin/fails/fail2/) shows that project can't be used at runtime block\n3. [Serialization problem](src/main/java/ru/vyarus/gradle/plugin/fails/fail3/) shows too broad serialization problem\n4. [Task and plugin serialization difference](src/main/java/ru/vyarus/gradle/plugin/fails/fail4/) shows the difference between tasks and plugins serialization\n\n## Implementation details\n\nRequires java 17 (multiline strings used to simplify tests).\n\nEach sample is in its own package. Relative test lay out in the same package.\n\nTests use Gradle TestKit. To demonstrate configuration cache, the same build must be run \nmultiple times:\n\n* First with configuration cache enabled (`--configuration-cache`) to create cache record\n* The second run shows behavior under the configuration cache\n* Some tests use a third execution to show cache invalidation.\n\nEach test run creates a temp directory as a project root (`@TempDir File projectDir`).\nBuild file created inside this directory.\n\nExample run:\n\n```java\nBuildResult result = GradleRunner.create()\n        .withProjectDir(projectDir)\n        .withArguments(List.of(\"myTask\", \"--configuration-cache\"))\n        .withPluginClasspath()\n        .forwardOutput()\n        .build();\n\n// validation\nresult.getOutput().contains(\"something\");\n```\n\nAll tests end with `KitTest` because usually gradle plugin projects also contain `ProjectBuilder`-based\ntests. There are no such tests, but convention preserved.\n\nAssertJ used because of its great errors output on strings comparison.\n\n## Configuration cache errors\n\nJust in case, when there is a configuration cache problem, gradle would idicate it like this:\n\n```\n\u003e Task :sample5Task\nTask executed: junit12045893691932608949\n\n1 problem was found storing the configuration cache.\n- Task `:sample5Task` of type `ru.vyarus.gradle.plugin.sample5.Sample5Task`: invocation of 'Task.project' at execution time is unsupported.\n  See https://docs.gradle.org/8.13/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution\n\n```\n\nDuring the real plugin project migration, the target is to eliminate all such errors.\n\nNote that different errors might appear in different cases: all plugin execution \"branches\" must be checked for \nconfiguration cache compatibility (gradle will not print all warnings at once - only for actually executed code).\n\n### TestKit jococo problem\n\nWhen running TestKit-based tests with enabled jococo plugin (for coverage), you'll have [an issue](https://docs.gradle.org/8.14.3/userguide/configuration_cache.html#config_cache:not_yet_implemented:testkit_build_with_java_agent):\n\n```\n1 problem was found storing the configuration cache.\n- Gradle runtime: support for using a Java agent with TestKit builds is not yet implemented with the configuration cache.\n  See https://docs.gradle.org/8.14.3/userguide/configuration_cache.html#config_cache:not_yet_implemented:testkit_build_with_java_agent\n```\n\nBut, it's not a critical problem: test must check that it was THE ONLY problem:\n\n```java\nBuildResult result = run('someTask', '--configuration-cache', '--configuration-cache-problems=warn');\nAssertions.assertThat(result.getOutput()).contains(\n                \"1 problem was found storing the configuration cache\",\n                \"Gradle runtime: support for using a Java agent with TestKit\",\n                \"Calculating task graph as no cached configuration is available for tasks:\"\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxvik%2Flearn-gradle-configuration-cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxvik%2Flearn-gradle-configuration-cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxvik%2Flearn-gradle-configuration-cache/lists"}