diff --git a/README.md b/README.md index 854c842..c8213fd 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ By default, this action aims to cache any and all reusable state that may be spe The state that is cached includes: - Any distributions downloaded to satisfy a `gradle-version` parameter ; - A subset of the Gradle User Home directory, including downloaded dependencies, wrapper distributions, and the local build cache ; -- Any [configuration-cache](https://docs.gradle.org/nightly/userguide/configuration_cache.html) data stored in the project `.gradle` directory. +- Any [configuration-cache](https://docs.gradle.org/nightly/userguide/configuration_cache.html) data stored in the project `.gradle` directory. (Only supported for Gradle 7 or higher.) To reduce the space required for caching, this action makes a best effort to reduce duplication in cache entries. diff --git a/src/cache-base.ts b/src/cache-base.ts index 0e7c6d6..9c037b8 100644 --- a/src/cache-base.ts +++ b/src/cache-base.ts @@ -170,7 +170,11 @@ export class GradleStateCache { const propertiesFile = path.resolve(gradleUserHome, 'gradle.properties') fs.appendFileSync(propertiesFile, 'org.gradle.daemon=false') - const initScriptFilenames = ['build-result-capture.init.gradle', 'project-root-capture.init.gradle'] + const initScriptFilenames = [ + 'build-result-capture.init.gradle', + 'project-root-capture.init.gradle', + 'project-root-capture.plugin.groovy' + ] for (const initScriptFilename of initScriptFilenames) { const initScriptContent = this.readResourceAsString(initScriptFilename) const initScriptPath = path.resolve(initScriptsDir, initScriptFilename) diff --git a/src/resources/project-root-capture.init.gradle b/src/resources/project-root-capture.init.gradle index 52e2a55..ea3e3d8 100644 --- a/src/resources/project-root-capture.init.gradle +++ b/src/resources/project-root-capture.init.gradle @@ -1,12 +1,10 @@ -// Capture the build root directory for each executed Gradle build. +import org.gradle.util.GradleVersion + // Only run against root build. Do not run against included builds. def isTopLevelBuild = gradle.getParent() == null -if (isTopLevelBuild) { - settingsEvaluated { settings -> - def projectRootEntry = settings.rootDir.absolutePath + '\n' - def projectRootList = new File(settings.gradle.gradleUserHomeDir, "project-roots.txt") - if (!projectRootList.exists() || !projectRootList.text.contains(projectRootEntry)) { - projectRootList << projectRootEntry - } - } -} \ No newline at end of file +// Only record configuration-cache entries for Gradle 7+ +def isAtLeastGradle7 = GradleVersion.current() >= GradleVersion.version('7.0') + +if (isTopLevelBuild && isAtLeastGradle7) { + apply from: 'project-root-capture.plugin.groovy' +} diff --git a/src/resources/project-root-capture.plugin.groovy b/src/resources/project-root-capture.plugin.groovy new file mode 100644 index 0000000..d4299f5 --- /dev/null +++ b/src/resources/project-root-capture.plugin.groovy @@ -0,0 +1,44 @@ + +/* + * Capture the build root directory for each executed Gradle build. + * This is used to save/restore configuration-cache files, so: + * - The implementation only makes sense if it's config-cache compatible + * - We only need to support Gradle 7+ + */ + +import org.gradle.tooling.events.* + +println "Applying Project tracker plugin" + +settingsEvaluated { settings -> + def rootDir = settings.rootDir.absolutePath + def rootListLocation = new File(settings.gradle.gradleUserHomeDir, "project-roots.txt").absolutePath + + def projectTracker = gradle.sharedServices.registerIfAbsent("gradle-build-action-projectRootTracker", ProjectTracker, { spec -> + spec.getParameters().getRootDir().set(rootDir); + spec.getParameters().getRootListLocation().set(rootListLocation); + }) + + gradle.services.get(BuildEventsListenerRegistry).onTaskCompletion(projectTracker) +} + +abstract class ProjectTracker implements BuildService, OperationCompletionListener, AutoCloseable { + interface Params extends BuildServiceParameters { + Property getRootDir(); + Property getRootListLocation(); + } + + public void onFinish(FinishEvent finishEvent) {} + + @Override + public void close() { + print "Closing ProjectTracker" + def rootDir = getParameters().getRootDir().get() + def rootDirEntry = rootDir + '\n' + def rootListFile = new File(getParameters().getRootListLocation().get()) + if (!rootListFile.exists() || !rootListFile.text.contains(rootDirEntry)) { + println "Added rootDir entry to list: ${rootDir}" + rootListFile << rootDirEntry + } + } +} \ No newline at end of file