Greetings. I’m trying to write a plugin that has a few different tasks of the same type, but with slightly different behavior. I’m following this guide and I’ve created a standalone project for the plugin. I’m specifically trying to follow the section [“Mapping Extension Properties to Task Properties”]
(https://docs.gradle.org/current/userguide/custom_plugins.html#sec:mapping_extension_properties_to_task_properties) . The plugin seems to work, but it seems to me that the Task properties are shared per Task class, and not per instance. I’m sure I’m doing something wrong here, and I’d appreciate some guidance. My code looks like this:
class VersioningPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
def patchExt = project.extensions.create('semantic', VersioningPluginExtension, project)
project.tasks.create('bumpPatch', PatchTask) {
bumpLevel = patchExt.bumpLevel
bumpLevel.set(BumpLevel.PATCH)
tagPrefix = extension.tagPrefix
version = extension.version
}
project.tasks.create('bumpMinor', PatchTask) {
bumpLevel = extension.bumpLevel
bumpLevel.set(BumpLevel.MINOR)
tagPrefix = extension.tagPrefix
version = extension.version
}
project.tasks.create('bumpMajor', PatchTask) {
bumpLevel = extension.bumpLevel
bumpLevel.set(BumpLevel.MAJOR)
tagPrefix = extension.tagPrefix
version = extension.version
}
}
}
class VersioningPluginExtension {
Property<BumpLevel> bumpLevel
Property<String> version
Property<String> tagPrefix
VersioningPluginExtension(Project project) {
bumpLevel = project.objects.property(BumpLevel)
version = project.objects.property(String)
tagPrefix = project.objects.property(String)
}
}
@Slf4j
class PatchTask extends DefaultTask {
// bump and version are properties that can be configured in an extension closure in build.gradle
Property<BumpLevel> bumpLevel
Property<String> version
Property<String> tagPrefix
// Bump the patch number of the release based on the latest git tag.
@TaskAction
String bumpVersion() {
// If the property is set through build.gradle, then use it, otherwise use git tagging to figure it out.
def prefix = tagPrefix && tagPrefix.isPresent() ? tagPrefix.get() : "*"
def level = bumpLevel && bumpLevel.isPresent() ? bumpLevel.get() : BumpLevel.PATCH
def ver = version && version.isPresent() ? version.get() : getTagVersion(prefix)
SemVer bumpedVersion = new SemVer(ver).bump(level)
log.debug("Bumping project version to $bumpedVersion")
return bumpedVersion.toString()
}
// Use git to find the latest tag that matches X.Y.Z
String getTagVersion(prefix) {
def proc = ['sh', '-c', 'git tag -l --sort=-taggerdate \'${prefix}\' | head -1'].execute()
log.debug("Searching for the latest tag using [$proc]")
def result = proc.in.text.find(/\d+\.\d+\.\d+/)
if (! result) {
log.error("Unable to find latest tag!")
}
return result
}
}
I have the three Task instances bumpPatch
, bumpMinor
, and bumpMajor
, and I would like to be able to configure them separately, but to share the property names. I.e. I’d like to be able to use a per Task closure in build.gradle
if this is possible:
semantic {
tagPrefix = ...
}
With my current approach, the properties that get set inside the various project.tasks.create(...)
calls seem to be shared between the Task instances. How do I make sure they are per Task instance but with the same name? Or am I taking the wrong approach on this? Any insights would be helpful. Thanks.