Recreating historic build dependencies

What’s the best way to recreate the results of a historic build?

We would like to be able to checkout the code for a given build and be able to recreate it exactly as it was when it was shipped, having all of the direct and transitive dependencies resolved to the exact version from that point in time.

We get close to this now by being explicit in our direct dependency declarations, but firstly this is a pain to maintain and secondly this actually only works correctly when the transitive dependencies are also fixed and not wild-carded. So it sort of works but isn’t perfect.

Is there some way to get gradle to only resolve dependencies based on some explicit dependency list - say one generated when a previous build was generated?

Or any other creative ways to address the problem?

You might want to look at Nebula’s Dependency Lock plug-in. I think that makes it easier to lock down versions. I think then it’s only a matter of producing the input for the plug-in on every build so you can go back to it. Of course, that breaks down if you’re using non-unique snapshots.

https://github.com/nebula-plugins/gradle-dependency-lock-plugin