Dependency resolution in plugin depending on the package from custom repository

I have a question regarding dependency resolution for plugins. I have the following situation:

• A plugin (https://github.com/Stvad/kask-gradle-plugin) that depends on the library I’ve developed - https://github.com/Stvad/kask
• The library is built/served by https://jitpack.io. It’s presented as a maven repo - maven(url = "https://jitpack.io")
• The plugin is published on the gradle plugin portal.

When I’m trying to use the plugin though I’m facing several problems:

• If I just use the plugin via id("org.stvad.kask") version "0.1.1" entry in plugins section, the project fails initial configuration, with the following error (basically gradle is looking for the library in the wrong place and not finding it):

Could not find com.github.Stvad:kask:-SNAPSHOT.
Searched in the following locations:
  - file:/Users/sitalov/.gradle/caches/4.10/embedded-kotlin-repo-1.2.60-2/repo/com/github/Stvad/kask/-SNAPSHOT/maven-metadata.xml
  - file:/Users/sitalov/.gradle/caches/4.10/embedded-kotlin-repo-1.2.60-2/repo/com/github/Stvad/kask/-SNAPSHOT/kask--SNAPSHOT.jar
  - https://plugins.gradle.org/m2/com/github/Stvad/kask/-SNAPSHOT/maven-metadata.xml
  - https://plugins.gradle.org/m2/com/github/Stvad/kask/-SNAPSHOT/kask--SNAPSHOT.pom
  - https://plugins.gradle.org/m2/com/github/Stvad/kask/-SNAPSHOT/kask--SNAPSHOT.jar
Required by:
    project : > org.stvad.kask:org.stvad.kask.gradle.plugin:0.1.1 > org.stvad:kask-gradle-plugin:0.1.1

I can work around that problem by adding the following configuration in the project settings:

pluginManagement {
    repositories {
        gradlePluginPortal()
        maven(url = "https://jitpack.io")
    }
}

Which, works, I guess =/, but I’m surprised I have to do this. So my first question is - can I avoid making users of the plugin do this?


I’m experiencing further problems with transitive dependencies resolution:
My understanding was that plugin dependencies should be transitively available to the project using that plugin. But it does not seem to work for me - in order to make the aforementioned library usable from the project that is applying the plugin, I had to explicitly declare repository and dependency configurations.

Which means that to use the plugin properly user would have to:

  1. apply it;
  2. change plugin repo configuration;
  3. add new repo to the project;
  4. add explicit library dependency to the project.

Which seems like a lot of effort.

What I want to achieve is the situation when a user of a plugin just needs to apply it and does not have to worry about any dependency declarations. I’d appreciate your advice on how I can achieve that!

Hi,

Can’t really see any better improvement regarding points 1 and 2.

Regarding the third point, your plugin could add the necessary repository itself:

boolean missing = rh.withType(MavenArtifactRepository).every { MavenArtifactRepository mar ->
    mar.url != 'https://jitpack.io'
}

if (missing) {
    project.repositories.maven { MavenArtifactRepository mar ->
        mar.name = 'jitpack'
        mar.url = 'https://jitpack.io'
    }
}

And the same goes for the last point:

// If you want to use java configuration names, make sure to apply the java plugin beforehand
project.dependencies.add 'configurationName', "${group}:${name}:${version}"

Consult the Gradle API to have an overview of what a plugin can set/unset on a Project: https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html

Hey Pierre! Thanks for suggestions and the examples!

Yep, I guess that’d work, I’m surprised that 2,3,4 are not the part of default/easily configurable functionality though =\

An alternative approach would be to make your plugin a fat jar so all your dependencies are packaged together and there is no longer a need for extra repositories. https://plugins.gradle.org/plugin/com.github.johnrengelman.shadow

It should be available to the build script of the project using that plugin, but not to the code of the project itself.
And providing such a feature in general would be wrong, as you would end up with runtime dependencies in your application that are only used to package said application.
As indicated above, if your plugin is also about adding runtime capabilities, it can configure them as part of its application to the project.

Thanks! I believe with this and making a plugin add repositories and dependencies to the project I can get to the user experience of just applying the plugin :slight_smile:

That makes sense. Thank you for elaboration!

I wonder if some kind of an easy way to mark dependencies as needing to be available for the package applying the plugin would be common enough of a use case to be supported by the core infrastructure.