publishPlugins does not generate POM correctly

I am raising this as a bug as I originally thought it related to the Gradle cloud infrastructure, but it seems to be in the publish plugin. I have found this whilst investigating this issue someone has raised against the vfs-plugin.

I have simplified the test to the following buildscript

configurations { example }
repositories {
  maven { url 'https://plugins.gradle.org/m2/' }
  jcenter()
}
dependencies { example 'org.ysb33r.gradle:vfs-gradle-plugin:1.0-beta5' }

which can be run with gradle -d -g FOO dep and cleaning FOO directory between runs.

Network #1 where it fails.

This fails to download because the POM it gets is incorrect. The debug log will show that

10:39:52.889 [DEBUG] [org.gradle.internal.resource.transport.http.HttpClientHelper] Performing HTTP GET: https://plugins.gradle.org/m2/org/ysb33r/gradle/vfs-gradle-plugin/1.0-beta5/vfs-gradle-plugin-1.0-beta5.pom
10:39:53.340 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection request: [route: {s}->https://plugins.gradle.org][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]
10:39:53.363 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection leased: [id: 0][route: {s}->https://plugins.gradle.org][total kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 10]
10:39:53.477 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnectionOperator] Connecting to plugins.gradle.org:443
10:39:54.107 [DEBUG] [org.apache.http.client.protocol.RequestAddCookies] CookieSpec selected: best-match
10:39:54.141 [DEBUG] [org.apache.http.client.protocol.RequestAuthCache] Auth cache not set in the context
10:39:54.145 [DEBUG] [org.apache.http.client.protocol.RequestTargetAuthentication] Target auth state: UNCHALLENGED
10:39:54.156 [DEBUG] [org.apache.http.client.protocol.RequestProxyAuthentication] Proxy auth state: UNCHALLENGED
10:39:54.158 [DEBUG] [org.apache.http.impl.client.SystemDefaultHttpClient] Attempt 1 to execute request
10:39:54.159 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Sending request: GET /m2/org/ysb33r/gradle/vfs-gradle-plugin/1.0-beta5/vfs-gradle-plugin-1.0-beta5.pom HTTP/1.1
10:39:54.244 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Receiving response: HTTP/1.1 303 See Other
10:39:54.256 [DEBUG] [org.gradle.internal.resource.transport.http.AlwaysRedirectRedirectStrategy] Redirect requested to location 'https://gradleware-plugins.s3.amazonaws.com/org.ysb33r.gradle/vfs-gradle-plugin/1.0-beta5/5df6435a29e97fe1cc3f968a6bd15cf6091a8e709ec13882045b06873fbdd697/vfs-gradle-plugin-1.0-beta5.pom'
10:39:54.263 [DEBUG] [org.apache.http.impl.client.SystemDefaultHttpClient] Resetting target auth state
10:39:54.264 [DEBUG] [org.apache.http.impl.client.SystemDefaultHttpClient] Redirecting to 'https://gradleware-plugins.s3.amazonaws.com/org.ysb33r.gradle/vfs-gradle-plugin/1.0-beta5/5df6435a29e97fe1cc3f968a6bd15cf6091a8e709ec13882045b06873fbdd697/vfs-gradle-plugin-1.0-beta5.pom' via {s}->https://gradleware-plugins.s3.amazonaws.com
10:39:54.270 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Connection 0.0.0.0:34055<->54.225.194.42:443 closed
10:39:54.272 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Connection 0.0.0.0:34055<->54.225.194.42:443 closed
10:39:54.273 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection released: [id: 0][route: {s}->https://plugins.gradle.org][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]
10:39:54.273 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection request: [route: {s}->https://gradleware-plugins.s3.amazonaws.com][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]
10:39:54.274 [DEBUG] [org.apache.http.impl.conn.PoolingClientConnectionManager] Connection leased: [id: 1][route: {s}->https://gradleware-plugins.s3.amazonaws.com][total kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 10]
10:39:54.387 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnectionOperator] Connecting to gradleware-plugins.s3.amazonaws.com:443
10:39:54.741 [DEBUG] [org.apache.http.client.protocol.RequestAddCookies] CookieSpec selected: best-match
10:39:54.742 [DEBUG] [org.apache.http.client.protocol.RequestAuthCache] Auth cache not set in the context
10:39:54.743 [DEBUG] [org.apache.http.client.protocol.RequestTargetAuthentication] Target auth state: UNCHALLENGED
10:39:54.744 [DEBUG] [org.apache.http.client.protocol.RequestProxyAuthentication] Proxy auth state: UNCHALLENGED
10:39:54.744 [DEBUG] [org.apache.http.impl.client.SystemDefaultHttpClient] Attempt 2 to execute request
10:39:54.745 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Sending request: GET /org.ysb33r.gradle/vfs-gradle-plugin/1.0-beta5/5df6435a29e97fe1cc3f968a6bd15cf6091a8e709ec13882045b06873fbdd697/vfs-gradle-plugin-1.0-beta5.pom HTTP/1.1
10:39:54.886 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Receiving response: HTTP/1.1 200 OK
10:39:54.893 [DEBUG] [org.apache.http.impl.client.SystemDefaultHttpClient] Connection can be kept alive indefinitely
10:39:54.922 [LIFECYCLE] [org.gradle.internal.resource.transfer.ProgressLoggingExternalResourceAccessor$ProgressLoggingExternalResource] Download https://plugins.gradle.org/m2/org/ysb33r/gradle/vfs-gradle-plugin/1.0-beta5/vfs-gradle-plugin-1.0-beta5.pom

A simple curl on https://gradleware-plugins.s3.amazonaws.com/org.ysb33r.gradle/vfs-gradle-plugin/1.0-beta5/5df6435a29e97fe1cc3f968a6bd15cf6091a8e709ec13882045b06873fbdd697/vfs-gradle-plugin-1.0-beta5.pom shows a POM containing the following incorrect snippet:

    <dependency>
      <groupId>org.ysb33r.groovy</groupId>
      <artifactId>dsl</artifactId>
      <version>1.0-beta5</version>
      <scope>compile</scope>
    </dependency>

The correct snippet should be

    <dependency>
      <groupId>org.ysb33r.groovy</groupId>
      <artifactId>groovy-vfs</artifactId>
      <version>1.0-beta5</version>
      <scope>compile</scope>
    </dependency>

If I remove the Gradle repo, then it resolves. The debug log for that case is

10:48:56.473 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Sending request: GET /org/ysb33r/gradle/vfs-gradle-plugin/1.0-beta5/vfs-gradle-plugin-1.0-beta5.pom HTTP/1.1
10:48:56.639 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Receiving response: HTTP/1.1 200 OK
10:48:56.655 [DEBUG] [org.apache.http.impl.client.SystemDefaultHttpClient] Connection can be kept alive indefinitely
10:48:56.702 [LIFECYCLE] [org.gradle.internal.resource.transfer.ProgressLoggingExternalResourceAccessor$ProgressLoggingExternalResource] Download https://jcenter.bintray.com/org/ysb33r/gradle/vfs-gradle-plugin/1.0-beta5/vfs-gradle-plugin-1.0-beta5.pom
10:48:56.708 [DEBUG] [org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor] Downloading https://jcenter.bintray.com/org/ysb33r/gradle/vfs-gradle-plugin/1.0-beta5/vfs-gradle-plugin-1.0-beta5.pom to /tmp/gradle_download1683793467655097630bin

More digging …

I have found this in the groovy-vfs plugin build.

build/poms/pom-default.xml
build/publish-generated-resources/pom.xml

Now pom-default.xml is the POM that gets pushed to bintray as part of the Bintray upload.
OTOH publish-generated-resources/pom.xml is generated by publishPlugins I believe and it is the one that get send to the Gradle pluglin portal. Any guesses as to which one has the broken POM ?

I think there might be an issue with regard to the publish plugin when one subproject depends on another an the name of the other subproject does not match the name of the artifact it produces

In the gradle plugin there exists a dependency

compile project( path:':dsl',configuration:'default')

whereas in the dsl subproject there is a line

archivesBaseName = 'groovy-vfs'

It should be pretty clear now where the discrepancy is arising.

I could not find the source repository for the plugin-publish-plugin and had to resort to the code in the source JAR. The issue is in PomWriter.addDependency and it relies on the hope that getName() will return the correct thing. Obviously for the above example this will not work.

if(dep instanceof DefaultProjectDependency) {
  // not sure if next line is totally correct - I just hastily converted it back from a Groovy test
  mavenDep.setArtifactId( (DefaultProjectDependency)dep.getDependencyProject().getArchivesBaseName() );
} else {
  mavenDep.setArtifactId(dep.getName());
}

but even that is not a 100% sure solution.

I concurred the problem as we only have access to published and signed artifacts at maven central or jcenter .

Thanks for reporting. I’ve raised GRADLE-3359 to track this issue.

The plugin-publish-plugin source is part of the plugin portal project, and is not open-sourced. I’ll make sure the devs are aware of this.

Looks like I also ran into the same (or at least a very similar) problem with the Dokka plugin. The Dokka Gradle plugin depends on a shadow jar. When I publish the plugin normally, the POM file references the correct artifact ID for the fatjar. When I publish to the plugin portal, the generated POM references the name of the module from which the fatjar is built, and the plugin doesn’t work because no such artifact is published.

The worst part of this is that there doesn’t seem to be any way to test a plugin before I publish it, so I discovered the problem only after the plugin has been published. Now the plugin portal contains a completely broken plugin with no possibility for me to delete it until I find a proper fix for this issue.

Thanks for reporting this @kotlin, I’ve created an extra ticket GRADLE-3509 for this issue.

This is a closely related problem to GRADLE-3359, but not entirely the same. We are inferring the artifactId of a different type of dependency here which for me warrants a separate task.

Could I please ask you to provide me with some more details and perhaps a link or code sample to look at?

This has now been fixed and rolled out in version 0.9.5 of the Plugin Publish plugin.

1 Like