I have made a plugin which will be working in two “modes”:
For the normal mode resolutionStrategy will be whatever is specified as the version i.e. if the version for a dependency is set to latest.integration then the latest integration is retrieved for the particular dependency, so essentially it will behave as gradle will normally do.
When we have to make a release version of an artifact a file is generated containing the versions that each dependency needs to be locked to. It is done in order to avoid to modify build gradle file.
I achieved this by having a custom resolutionStrategy in pluginManager in settings and configurations.
In order to not have duplicated code I have created a groovy script which is applied to the pluginManager, the buildScript and the project, and it works as expected. The groovy script gets downloaded from a repository via a hardcoded url.
My challenge is now that after it has been working for a long time more and more projects is using this logic. and some enhancements needs to be done, and given that all projects will always take the latest it means that whatever change I made will have an effect on all the projects using this plugin, which means that one has to be extremely careful not to break any of the project, which potentially can be quite difficult.
So I figured that I would like to be able to select certain version of a dependency while on others they should just use the latest integration.
So in order to achieve this I would like to add some logic that would be able to select a version for each project e.g. for project abc then the version of a dependency A should be e.g. 1.20.0 and but for project def the version of a dependency A should be e.g. 1.25.0 and for any other the version of A should be latest.integration. This behaviour would also help if I would like to upgrade from gradle 4.x to 5.x and I do not want to update all projects at the same time.
What I would like to avoid is to go through all 100 projects and change the hardcoded url every time a new strategy needs to be implemented so I thought about using the built in dependency mechanism to get the latest version selection logic down.
I found out that the resolutionStrategy can only be changed until an item has been resolved, so I thought about making a hack, where the resolutionStrategy used act as proxy for some logic that will actually do the version selection.
So I imagined something along these line:
resolutionStrategy {
eachPlugin { it ->
delegate.resolve(it)
}
}
and then in the build gradle script I would have something like
plugins {
id(‘version-selector’) version “LATEST”
id(‘my-plugin1’) version “LATEST”
id(‘my-plugin2’) version “LATEST”
}
LATEST is used as gradle 4.9 does not support dynamic version so I made a hack to support this, but it is irrelevant for the discussion. But what should happen is that the version-selector should retrieve the latest version of the version-selector which contains the delegate needed for the resolution strategy.
And then the delegate should be instantiated and injected somehow into the resolutionStrategy.
Using the above example it would not be possible inject the value into the resolutionStrategy so I thought about having some container object and do some lazy initialisation so that resolutionStrategy I would look for the delegate and when applying the version-selector the delegate needed to be stored somewhere where it can be retrieved by the resolutionStrategy.
What I can’t seem to figure where it will be possible to store the delegate that be retrieved from the resolutionStrategy.
I tried to see if it would be possible to store the delegate into the ext, extensions, conventions, however they do not seems to be the same when running in the resolutionStrategy and in the build script and therefore this cannot be easily transferred.
So I would like to ask if there is a better way to do what I am intended to do, which is to be able to store something somewhere in gradle and can easily be retrieved by the resolutionStrategy.
Alternatively the resolutionStrategy needs to be implemented in another way so if any has some suggestion it would be highly appreciated.