Skip to content

diffplug/cache-horizon

Repository files navigation

Cache Horizon:
Use gradle build cache for a group of tasks

Gradle plugin Maven central Apache 2.0

Changelog Javadoc Live chat JitCI

The problem

Take the following task trees:

[install node] -> [npm install] -+-> [npm run compileSass      ] + -> [npm run concatMinify]
                                 +-> [npm run compileTypescript] +

[start docker] -> [run command in docker] -> [stop docker]
  • the group of tasks can easily be defined as f(inputs) = output_files
  • but individually they can't, because some steps modify the environment
    • you can't cache start docker ...
  • if you could somehow cache the group, then you could avoid not just a task, but an entire toolchain
    • ...but you can easily cache f(dockerfile, input_files) -> output_files

A solution

plugins {
    id 'com.diffplug.cache-horizon'
}

cacheHorizon {
    add 'nodeInstall', 'npmInstall', 'compileSass', 'compileTypescript'
    inputsAndOutputs {
        inputs.property('nodeVersion', nodeTask.nodeVersion)
        inputs.file('package-lock.json').withPathSensitivity(PathSensitivity.RELATIVE)
        inputs.dir('src/main/typescript').withPathSensitivity(PathSensitivity.RELATIVE)
        outputs.file('build/index.js')
    }
}

This will add two tasks with the following dependency arrangement

                        +------------------------------+
cacheHorizonIsCached -> | nodeInstall, npmInstall, ... | -> cacheHorizon
                        +------------------------------+

When cacheHorizonIsCached executes, it looks forward to check if cacheHorizon is able to be restored from cache. If it is, then it disables nodeInstall, npmInstall, etc. When cacheHorizon eventually runs, it will just restore index.js from cache, avoiding all the intermediate work.

DANGER no outside task should depend on anything within the horizon (e.g. test dependsOn compileTypescript is bad, it should instead depend on cacheHorizon). It is fine if tasks within the horizon depend on anything outside the horizon (e.g. compileTypescript dependsOn lintTypescript is fine).

Multiple cache horizons in one project

Usually you only need one cacheHorizon per project. But if you want more, you can do this:

cacheHorizon {
    named 'dockerHorizon', {
        add 'dockerStart', 'dockerRun', 'dockerStop'
        inputsAndOutputs { ... }
    }

Now you'll have dockerHorizon and dockerHorizonIsCached tasks.

Limitations 🔴This project has not been implemented🔴

We started to implement it, got stuck, and found an easier way around. We're publishing what we did in case it helps you get to the finish line. See this issue for the latest on our progress. If somebody builds something else which solves this problem we'll link out from there.

Cache horizon uses Gradle's internal API, so there will be compatibility delays (e.g. when Gradle N comes out, it might be a little while until cache-horizon has been tested and fixed for the new version).

Acknowledgements

About

Gradle build cache for a group of tasks

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages