Specify minimum gradle version for a plugin

My plugin, macAppBundle, gives warning in 4.3-rc-2 due to nulls in task.inputs.property for unset properties. The nulls are apparently now a problem and the official way to deal with these is to flag these is
task.inputs.property(…).optional(true)

I am happy to fix this. But unfortunately, the .optional() method does not exist prior to 4.3, and so I am forced to choose between a bit of a hack to avoid the warning message if I want the plugin to remain usable in both 4.3 and prior versions.

Two questions, first, is there a way for a plugin to either specify the minimum version of gradle? This would allow me to release a new version of the plugin targeting >=4.3 while also letting users who are still on older versions of gradle know that they should not upgrade the plugin. It would be nice if this were part of the official gradle plugin portal. But if not, then can I programmatically find and check the current gradle version being >= 4.3 so I can warn the user on launch? I found these two posts, but neither seems to be current, or at least the classes they reference are not in the public API docs. I guess I can use gradle.gradleVersion, but parsing strings to find <= seems fraught with peril. And given the fact that a big part of gradle is handling dependency versioning issues, seems like I shouldn’t have to hack that together. I like the idea as suggested in the first post of a plugin saying something like:

GradleVersion.require(>=4.3)

Second question, is this even the right way to go about this? How should task InputProperties that are optional be handled in a way that does not require the latest gradle? Is optional(true) the best way or should I use something else?

thanks

I don’t have a direct solution for you, but perhaps you can avoid the issue. If you can refactor things in such a way that you can use the task property annotations instead of accessing the task inputs directly, then you should be able to use @Optional in either version of Gradle.

For example:

class SuperTask extends DefaultTask
{
    @Optional
    @Input
    String superProperty

    @TaskAction
    void doSuperWork() { println superProperty }
}

// plugin's apply() method
project.tasks.create( 'super', SuperTask )

Besides the @Chris_Dore comment above, some things you can do:

void apply(Project project) {
  if(GradleVersion.current() >= GradleVersion.version('1.2.3')) {
    // call project code for newer versions
  } else {
    // call project code for older versions
  }
}

The above is typical for plugin code that applies reasonably differently functionality dependent on version. (GradleTest for instance uses this to apply legacy behvaiour when it detects versions on Gradle prior to Gradle 2.13).

Probably in your case above you rather need a decision based closer to the place where the property code is called. Assumuing that this is something that is done programmatically within in your plugin’s code base, simply do

@CompileDynamic
private void setOptionalInputProperty(final String s, Object o ) {
  if(GradleVersion.current() >= GradleVersion.version('4.3')) {
    inputs.property(s,o).optional(true)
  } else {
    inputs.property(s,o)
  }
}

The above will allow to keep the rest of the code statically compiled, but allow the setting internally within the task.

If this is in the build script for the plugin project itself, you can use the decision is a similar fashion or make it a bit more generic by placing it in the ext block of the task or project.

It would be great if gradle read a file for that info. In my case I copy the GroovyPlugin code as mine is pretty much doing a similar thing but for html. SourceSets exists in 5.5 but not in 5.6. In 5.6 it’s JVMPluginsHelper which doesn’t exist in 5.5. I can’t possibly compile against 2 different gradle versions. A standard way of doing the versioning would be really really nice.

thanks,
Dean

That’s why I created the Grolifant library, so that it can deal with a lot of that rather than the plugin developer. Still a lot of scope for adding new stuff there, but in some cases doing the check in the code remains the easiest.

I have had to resort in some cases to using reflection to determine which features exist as a simple version test was not sufficient.

Also I test with GradleTest in order to cover a large range of Gradle versions.