I need my gradle plugin to determine its own version when applied in the user project so that it can further configure the project with some dependencies accordingly. How can I achieve this in the best way?
More context on the plugin - it’s a supplementary plugin for an internal library and will be released together with the same version, just like spring-boot gradle plugin.
You can obtain the artifact and its metadata added to the build classpath with the following source code (known to work with Gradle 6.5, both with plugins applied with legacy buildscript and plugins blocks:
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
public class Foo implements Plugin<Project> {
@Override
public void apply(Project project) {
final Configuration classpath = project.getBuildscript().getConfigurations().getByName("classpath");
final String version = classpath.getResolvedConfiguration().getResolvedArtifacts().stream()
.map(artifact -> artifact.getModuleVersion().getId())
.filter(id -> "org.example".equals(id.getGroup()) && "foo".equals(id.getName()))
.findAny()
.map(ModuleVersionIdentifier::getVersion)
.orElseThrow(() -> new IllegalStateException("foo plugin has been deployed with wrong coordinates: expected group to be 'org.example' and name to be 'foo'"));
project.getLogger().lifecycle("applied plugin with version [{}]", version);
}
}
You could include a file (eg a property file) inside your plugin’s jar which contains the project version. This file could be generated dynamically as part of your build.
Properties props = new Properties()
props.load(getClass().getClassloader().getResourceAsStream("myplugin.properties"))
String version = props.getProperty("version")
I implemented the approach suggested by @Pierre1 first and as he mentioned it worked fine. However, it fails for a multi-module gradle project where the plugin is added in the root projects as apply false, then applied without a version in the subproject. In this case, the plugin artifact isn’t found in the project buildscript classpath. So I tried to search for it in the parent projects recursively as below:
This works fine for the failure scenario described above. However, in this case, gradle complains that the project is trying to resolve artifacts of a different project.
Therefore, I switched to the second approach suggested by @Lance. This approach makes the version inference logic a lot simpler in the plugin source code with a bit of setup in build.gradle. Another important aspect of this approach is that, it’s very friendly with functional tests with gradle-test-kit. Thus, it’s possible to write a functional test simulating the failure scenario and make sure it actually works.