Gradle Plugin Portal transitive dependencies and the pluginRepositories block

I was testing out the pluginRepositories I think I may run into an issue when a plugin is vended with a dependency on another plugin on the Gradle Plugin Portal. I was trying to compose a, sort of, “umbrella” type plugin that applies and configures other plugins.

It doesn’t seem the plugin classpath is resolved for the gradlePluginPortal() for transitive type plugin dependencies.

Reproducing

  • Java 8
  • Using Gradle Build Tool wrapper 2.14

project1

  1. In src/main/groovy/mkobit/gradle/MyPlugin.groovy

    package mkobit.gradle
    
    import groovy.transform.CompileStatic
    
    import org.gradle.api.Plugin
    import org.gradle.api.Project
    import org.gradle.model.RuleSource
    
    import com.palantir.gradle.docker.PalantirDockerPlugin
    
    @CompileStatic
    class MyPlugin implements Plugin<Project> {
    
      @Override
      void apply(Project project) {
        project.pluginManager.apply(PalantirDockerPlugin)
      }
    }
    
  2. In build.gradle

    plugins {
      id 'groovy'
      id 'java-gradle-plugin'
      id 'maven-publish'
    }
    
    targetCompatibility = sourceCompatibility = JavaVersion.VERSION_1_8
    
    group = 'mkobit.gradle'
    version = '0.1.0'
    
    repositories {
      maven {
        url 'https://plugins.gradle.org/m2'
      }
    }
    
    dependencies {
      compile 'gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.8.0'
    }
    
    gradlePlugin {
      plugins {
        myPlugin {
          id = 'mkobit.gradle.myplugin'
          implementationClass = 'mkobit.gradle.MyPlugin'
        }
      }
    }
    
    model {
      tasks {
        wrapper {
          gradleVersion = '2.14'
        }
      }
    }
    
  3. In settings.gradle

    pluginRepositories {
      // Use local for project1 dependency
      maven {
        url 'file:///Users/mkobit/.m2/repository'
      }
      // <2>
      // gradlePluginPortal()
    
      // <3>
      //  maven {
      //    url 'https://plugins.gradle.org/m2'
      //  }
    }
    
    rootProject.name = 'project2'
    

Reproducing

  1. Publish project1 locally

    • cd project1
    • ./gradlew publishToMavenLocal
  2. Run ./gradlew build in project2, watch it fail

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring root project 'project2'.
    > Could not resolve all dependencies for configuration ':classpath'.
       > Could not find gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.8.0.
         Searched in the following locations:
             file:/Users/mkobit/.m2/repository/gradle/plugin/com/palantir/gradle/docker/gradle-docker/0.8.0/gradle-docker-0.8.0.pom
             file:/Users/mkobit/.m2/repository/gradle/plugin/com/palantir/gradle/docker/gradle-docker/0.8.0/gradle-docker-0.8.0.jar
         Required by:
             :project2:unspecified > mkobit.gradle.myplugin:mkobit.gradle.myplugin.gradle.plugin:0.1.0 > mkobit.gradle:project1:0.1.0
    
  3. Uncomment out <1> in project2, run ./gradlew build.
    Plugin is successfully applied (build still fails because of applied plugin)

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring root project 'project2'.
    > name is a required docker configuration item.
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
    
  4. Comment out <1>, uncomment <2>, run ./gradlew build.

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring root project 'project2'.
    > Could not resolve all dependencies for configuration ':classpath'.
       > Could not find gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.8.0.
         Searched in the following locations:
             file:/Users/mkobit/.m2/repository/gradle/plugin/com/palantir/gradle/docker/gradle-docker/0.8.0/gradle-docker-0.8.0.pom
             file:/Users/mkobit/.m2/repository/gradle/plugin/com/palantir/gradle/docker/gradle-docker/0.8.0/gradle-docker-0.8.0.jar
         Required by:
             :project2:unspecified > mkobit.gradle.myplugin:mkobit.gradle.myplugin.gradle.plugin:0.1.0 > mkobit.gradle:project1:0.1.0
    
  5. Comment out <2>, uncomment <3>, run ./gradlew build.
    Plugin is successfully applied (build still fails because of applied plugin)

    FAILURE: Build failed with an exception.
    
    * What went wrong:
    A problem occurred configuring root project 'project2'.
    > name is a required docker configuration item.
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
    

Plugin classpath resolution

So my confusion above comes from <2> and <3>.
It seems to me that the gradlePluginPortal() would add it as a repository for resolution, but it does not seem to do the same thing.
My thoughts would be that <2> would work, but maybe I am misunderstanding how the plugin resolution works.

I haven’t tried to trace through Gradle’s source to find the bug yet, but is this expected behavior?

Hi Mike,

this is a known issue when a local/company plugin depends on a plugin in the portal. The workaround is to add both #2 and #3 to your settings.gradle.

Cheers,
Stefan

1 Like