Artikel 4: Het valkuil van de Gradle-configuratiecache
Gepubliceerd op 26 September 2025
Doelgroep: Gradle-ontwikkelaars die al eens magisch of onverwacht build-gedrag zijn tegengekomen.
Inleiding
In ons avontuur bij het maken van de plugin`site-baker`, we hebben een strikte TDD-aanpak gevolgd. Elke functionaliteit werd getest, gevalideerd, en we gingen vooruit met vertrouwen. En toen, op een dag, kwam het onverwachte. De builds begonnen zich onvoorspelbaar te gedragen. Wijzigingen in de logica van de plugin of in de configuratiebestanden leken te worden genegeerd, en onze functionele tests, die vroeger betrouwbaar waren, faalden zonder duidelijke reden.
Deze soort probleem kan ongelooflijk frustrerend zijn. Het stelt de betrouwbaarheid van het instrument en de geldigheid van onze code ter discussie. Na een intensieve debugging-sessie, leGradle configuratie-cache.
Het symptoom: spookbuilds
Het probleem manifesteerde zich op verschillende manieren:
-
Ik wijzigde een string in een taak`println`maar de oude tekenreeks bleef tijdens de uitvoering worden weergegeven.
-
Ik veranderde een waarde in mijn bestand`managed-jbake-context.yml`, maar de plugin gedroeg zich alsof het bestand niet was gewijzigd.
-
De functionele tests, die testprojecten op de vlucht maken, faalden omdat de plug‑in de pas aangemaakte configuratiebestanden niet leek te detecteren.
Alles verliep alsof Gradle een 'fantomaversie' van onze build uitvoerde, onze recentste wijzigingen negerend.
De enquête: Wat is de configuratie-cache?
De configuratie-cache is een relatief moderne en extreem krachtige functie van Gradle, standaard ingeschakeld in de nieuwere versies. Het doel is om de builds sneller te maken.
-
Tijdens de eerste uitvoering, voert Gradle de fase vanConfiguratie(lezing van de`build.gradle.kts`, aanmaken van de taken, oplossing van afhankelijkheden) en bouwt een taakgrafiek.
-
Aan het einde van deze fase, Gradleserialiseer deze taakgrafen slaat het op in de cache.
-
Bij volgende uitvoeringen, als er niets gewijzigd is (buildscripts,
gradle.properties, etc.), Gradleslaat de configuratiefase volledig overen hergebruik de in cache geplaatste taakengrafiek.
De tijdsbesparing is spectaculair bij grote projecten. Echter, deze prestatie heeft een prijs: ze legt strikte regels op voor de manier waarop plugins moeten worden geschreven.
@startuml
start
:Première exécution;
:Phase de Configuration;
:Création du graphe de tâches;
:Mise en cache du graphe;
:Phase d'Exécution;
end
start
:Exécution suivante;
if (Cache valide ?) then (oui)
:Restauration du graphe depuis le cache;
note right
La phase de configuration
est sautée !
end note
else (non)
:Phase de Configuration;
:Mise à jour du cache;
endif
:Phase d'Exécution;
stop
@enduml
De oorzaak van het probleem: een niet‑conforme plug‑in
Onze plugin`site-baker`schond, zonder het te weten, verschillende regels van de configuratie-cache. Om een taken-graaf serialiseerbaar te zijn, mogen taken geen verwijzingen bevatten naar complexe objecten zoals het object`Project`of bestanden op een willekeurige manier te lezen tijdens de uitvoeringsfase.
Onze belangrijkste fout was om de inhoud van het YAML-bestand rechtstreeks binnen de taakuitvoeringslogica te lezen, met behulp van een verwijzing naar het pad dat in onze extensie is opgeslagen. Deze aanpak is onverenigbaar met de cache omdat Gradle niet kan weten of de inhoud van het bestand is gewijzigd als deze lezing niet wordt gemodelleerd als eeninvoer van taak (Task Input).
De Tijdelijke Oplossing : Schakel de Cache uit
Om ons te ontgrendelen en een voorspelbaar buildgedrag te herstellen, was de snelste oplossing het uitschakelen van de configuratiecache. Het volstaat om de volgende regel in het bestand toe te voegen.gradle.properties`van het project dat de plugin gebruikt (of in ons geval, het testproject)`site-baker).
# site-baker/gradle.properties
org.gradle.configuration-cache=false
Onmiddellijk kregen de builds hun normale gedrag terug. Elke uitvoering startte de configuratiefase opnieuw en onze wijzigingen werden meegenomen.
Echter, dit is een workaround, geen duurzame oplossing. Het offerd de prestaties en lost het onderliggende probleem van onze plugin niet op.
De ware oplossing : de plugin compatibel maken
Voor een plugin een goede burger te zijn in het moderne Gradle-ecosysteem, moet deze compatibel zijn met de configuratie-cache. Dit houdt in dat we moeten nadenken over de manier waarop gegevens naar onze taken stromen.
De sleutel is om de te gebruikenLeverancier API’svan Gradle. In plaats van directe waarden door te geven (zoals een`String` ou un File) aan onze taken, moeten we doorbrengen`Property<T>`of de`Provider<T>`.
-
Declareer de taakinvoer:De taak die het YAML-bestand parseert moet dit bestand als invoer declareren. Daarvoor wordt de annotatie gebruikt`@InputFile`.
[source,kotlin] (No text provided to translate) @get:InputFile abstract val configFile: RegularFileProperty ----