Plugins block with custom repo has severe limitations

I am very excited by the potential for the plugins block with custom repositories introduced in 2.14. However, while attempting to implement this with my custom Maven repository, I encountered a number of severe limitations, which in my case has blocked my ability to continue with the feature.

  1. While the plugins block supports using a “version” attribute, it does not support dynamic versions (i.e. ones using “+”). Since we rely on dynamic versions, this is a blocker and rather surprising given the support for dynamic versions in the original plugin mechanism.

  2. There is no mechanism for providing a global pluginRepositories block. Because I only use a single custom repository, this limitation means that I must duplicate the repository information in every project.

  3. You cannot reference global gradle.properties values in the settings.gradle pluginRepositories block. This means that not only must I duplicate the pluginRepositories block in every project, I cannot use a property to avoid hard coding the URL value. Actually, I figured a workaround, by explicitly loading the ~/.gradle/gradle.properties file using the Properties class. Clearly, that is unnecessary and clumsy boilerplate.

I am excited to be able to use the plugins capability once these limitations are addressed.

Thanks,
Baron

1 Like

I’d be very interested in seeing your workaround. I, too am looking for some way out of the straitjacket of this potentially exciting feature. See https://discuss.gradle.org/t/restriction-that-plugin-versions-must-be-string-literals-is-onerous/18152.

On the subject of settings.gradle, are you aware of any clear description of what kinds of things can or cannot be placed there? If I knew this, I might find some workarounds.

My investigation showed that global gradle.properties values are available in the settings.gradle but not within the pluginRepositories block. So to work around this, I resorted to using the Java Properties class, directly loading ~/.gradle/gradle.propties into it, and then just calling its getProperty method. Essentially, put the following within your pluginRepositories block and use the myReopUrl as the Maven/Ivy url value:

final Properties props = new Properties();
props.load(new FileReader(System.getProperty("user.home") + "/.gradle/gradle.properties"));
final String myRepoUrl = props.getProperty("myRepoUrl");

It would be great to hear from the Gradle folks whether their roadmap for the plugins block will address any of these deficiencies.

Yes, there is a plan to address some of these limitations. @st_oehme, can you provide any more details?

@Baron_Roberts We are considering all of the points you mentioned for the next iteration on the plugins DSL.

Regarding the pluginRepositories block specifically: We deliberately locked it down so you cannot access the Settings API at that point. This resulted in also blocking access to properties, which are clearly needed (e.g. for passwords). Removing this limitation is the highest priority of those you mentioned.

Thanks @mark_vieira and @st_oehme for the update! I am really glad to hear the plans and am super excited that in the near future my scripts can be made cleaner thanks to the plugins block and your efforts. Cheers

Just to put my two cents in, I was also very pleased with the new pluginRepositories features.

Previously our workaround for developing plugins applied to various internal projects was to add the plugin repository as a git submodule in buildSrc. Needless to say, this was a kludge, and the ensuing full build of the plugin with every gradle invocation in the main project was a big waste of time.

So this is a huge step in the right direction.

But when working with plugins under development, I’ve found that I cannot resolve SNAPSHOT versions; trying to do so immediately triggers the error

(snapshot plugin versions are not supported)

This seems like an arbitrary limitation (cf. https://github.com/gradle/gradle/blob/7e5343e01c8635d4318363a850a5418aa42aac53/subprojects/plugin-use/src/main/java/org/gradle/plugin/use/resolve/internal/ArtifactRepositoryPluginResolver.java#L47-L49). I think everyone here understands what SNAPSHOT versions are, and that they shouldn’t be used in production, but for internal testing it makes sense, and it seems a bit heavy-handed for gradle to actively prevent it. The workaround for a plugin developer is changing the version string to pretend it’s stable, just to test a plugin, which is rather silly, and might even lead to accidental publishing of unstable plugins, which defeats the purpose.

A minor detail is that the documentation could be slightly more explicit that providing any custom plugin repositories will block resolution of plugins from the default place (the gradle plugins portal), until the gradlePluginPortal() is explicitly added as well.

Finally, I would love to see popular shorthands like mavenLocal() and jcenter() available in the pluginRepositories block in addition to the provided gradlePluginPortal().

2 Likes

A quick update: Gradle 3.0 will allow accessing properties in the pluginRepositories block.

Excellent! How about dynamic and SNAPSHOT property support in the plugins block?

We have a planned project for enhancing the plugins block, but haven’t scheduled it yet.

I would really like to see a global pluginRepositories block in init.gradle (allProjects) (or a global settings.gradle), as well as support for mavenLocal() (for development).

We are using a shared init.gradle to configure our company repositories:

  • libs-release
  • libs-snapshot

Being able to to resolve our plugins-release repos the same way would be gold. From our perspective the repository URLs, credentials and resolutions is an infrastructure/environment concern and should not be part of a project specific settings.gradle.

Example init.gradle:

allprojects {

    /* Resolving dependencies */
    repositories {
        mavenLocal()
        maven {
            name "releases"
            url "${artifactory_contexturl}libs-release"
        }
        maven {
            name "snapshots"
            url "${artifactory_contexturl}libs-snapshot"
        }
    }

    /* Resolving plugins */
    pluginRepositories {  // Please, pretty please.
        mavenLocal()
        maven {
            name "plugins"
            url "${artifactory_contexturl}plugins-release"
        }
    }
}
1 Like

We hear you, this will be part of the next milestone of the plugin DSL.

Any updates on this? As a large enterprise trying to ship a standard custom distribution that reduces boilerplate setup for thousands of projects - not being able to configure the plugin repositories in an init script/init plugin is a showstopper for us. We can’t expect thousands of projects in our organization to have to have a settings.gradle file and to put this stuff in there.

@ethankhall is currently working on a contribution that will make this possible.

1 Like

@eric_deandrea my change won’t let dynamic versions work without some code, but you will be able to put it into an init-script.

1 Like

As far as I can tell this is not working in Gradle 3.4. Has this ever been allowed? Can someone indicate in what version(s) is it expected to work?

+1 Can someone chime in with the latest state of this? @st_oehme said above, about a year ago, that the next milestone of the plugin DSL would bring changes that made it possible to configure this stuff in init scripts, and other things. What’s the status of that?

The pluginManagement block (since Gradle 3.5) supersedes the pluginRepositories block and is now a normal method on Settings. This specifically means you can call it from an init script using the settingsEvaluated hook. Does that solve your use case?

1 Like

Oh neat! It looks like it will, we’ll give it a shot. Thanks.