I’m working on a Gradle plugin whose goal is to grab a particular zip file from maven central, unzip it, and set an environment variable pointing to the unzipped location for tests.
Currently the version of the zip file is hardcoded in my plugin, but I would ideally like to allow users to override the version as desired. However, I’m not sure if this is possible since plugin dependencies may be resolved before extensions are taken into account. Any help or advice would be appreciated.
That’s doable. You can use defaultDependencies {} to specify dependencies that should be used for a given configuration if none are provided. This would let someone use a completely different set of coordinates, if necessary.
A few comments about your plugin so far:
It’s frowned upon to define repositories in your plugin unless you absolutely need it. Including repositories makes it more difficult for others to use your plugin because they may have their own mirrors they would prefer to use.
You should avoid resolving configurations at configuration time.
For instance, configurations.geodeIntegration.find {} requires that Gradle resolve and download the geodeIntegration files before it can do anything else.
If you can avoid it, don’t pass absolute paths as environment variables or system properties to the Test task as that reduces build cacheability because Gradle will see absolute paths and not allow builds with different absolute paths to share artifacts.
If tests will rely on the contents of the outputDir, those files should be an input to the Test tasks too.
Here’s a stab at making the plugin more idiomatic. You can plop this into a build.gradle and you should be able to run gradle test and see it populate build/install/apache-geode.
class GeodeExtension {
String version = "1.3.0-SNAPSHOT"
}
class GeodeIntegration implements Plugin<Project> {
@Override
void apply(Project project) {
def extension = project.extensions.create("geodeIntegration", GeodeExtension)
project.configurations {
geodeIntegration {
defaultDependencies { dependencies ->
dependencies.add(project.dependencies.create("org.apache.geode:apache-geode:${extension.version}@zip"))
}
}
}
def installGeode = project.task('installGeode', type: Sync) {
dependsOn project.configurations.geodeIntegration
from {
project.zipTree(project.configurations.geodeIntegration.singleFile)
}
// Strip version number from base zip name
eachFile { fcd ->
fcd.path = (fcd.path - ~/apache-geode-[0-9.]+(-SNAPSHOT)?/)
}
into "${project.buildDir}/install/apache-geode/"
}
project.tasks.withType(Test) {
environment GEODE_HOME: installGeode.destinationDir
dependsOn installGeode
}
}
}
// Just for the example to work:
repositories {
mavenCentral()
maven { url 'https://repository.apache.org/content/repositories/snapshots' }
maven { url 'https://repository.apache.org/content/repositories/releases' }
}
apply plugin: GeodeIntegration
apply plugin: 'java'
Hope this helps. Be sure to check out the testing guide for how to test your plugin with TestKit.
Thanks so much Sterling. Your answer goes above and beyond, it was super helpful. Out of curiosity, would you mind explaining what effect the “@zip” suffix has on the dependency? I wasn’t able to find a docs page to explain it. Thanks again!
Using @zip tells Gradle to look for an artifact with that extension vs the default .jar. There’s also a short section in the user guide about this too (but it uses the “long” notation).