My build manages versions numbers automatically and so dependencies tend to expressed as a range. I’ve noticed the range is passed through to the POM as a range whereas I want to pass through (publish) the resolved dependency. Is there a mechanism in gradle I’m missing to achieve this? I can see there is a PomDependenciesConverter abstraction but it looks like it is not something I can override
Therefore it looks like I’ll need to use ‘pom#whenConfigured’ and then
walk through the dependencies on the pom - search for the corresponding project configuration
get the ResolvedConfiguration from that - match up the POM dependency with the resolved one - update the POM dependency version to match
Is there a better way?
IMO the default behaviour should be to realise a static set of dependencies when I do an install rather than pass through an unstable dependency. This is how ivy works in this case fwiw.
I have the same question, but on the Ivy side. I would prefer to see the resolved version number in ivy.xml.
When I use Gradle to publish to an Ivy repo, the generated ivy.xml sets ‘rev’ equal to ‘1.0.+’ instead of ‘1.0.23’ (for example). I guess your comment about Ivy describes its behavior when it is not used via Gradle?
(apparently working) solution for maven as follows, to be called from a ‘pom.whenConfigured’
I’m sure my groovy is not especially idiomatic but it seems to work.
/**
* Realises a Maven dependency into a specific version.
* @param dep the dependency, expected to be of type {@link org.apache.maven.model.Dependency} otherwise there may
* be trouble ahead!
*/
void realiseDependency(def dep) {
if (isDynamic(dep)) {
project.logger.info("Realising $dep into a specific revision")
Configuration conf = project.configurations.findByName(dep.scope)
if (conf == null) {
throw new BuildException("Unable to realise $dep due to missing configuration, aborting as dependency tree will be unstable")
} else {
def matches = conf.resolvedConfiguration.resolvedArtifacts.findAll {
it.moduleVersion.id.group.equals(dep.groupId) && it.moduleVersion.id.name.equals(dep.artifactId) && (it.classifier == null || (it.classifier != null && it.classifier.equals(dep.classifier)))
}
if (matches.size() > 1)
throw new BuildException("Unable to realise $dep due to multiple resolved dependencies, aborting as dependency tree will be unstable")
else
matches.each { dep.version = it.moduleVersion.id.version }
}
}
}
boolean isDynamic(def dep) {
return dep.version.any { it == '[' || it == ']' || it == '(' || it == ')' || it == '+' }
}
FWIW I don’t see any equivalent hooks for ivy. It all seems to be baked in via the internal ivyservice & specifically the ‘org.gradle.api.internal.artifacts.ivyservice.moduleconverter.dependencies.DependencyDescriptorFactory’