Regression introduced between Gradle 2.2.1 and 2.3 or higher

I found a regression (or at least incompatible change I don’t understand) between Gradle 2.2.1 and Gradle 2.3 or higher.

Steps to reproduce

  • git clone https://github.com/huxi/sulky.git
  • cd sulky
  • In build.gradle, replace the GPG key id with one of yours.
    allprojects { ext.'signing.keyId' = '740A1840' }
  • gradlew --no-daemon -Drelease=true --recompile-scripts
  • cd ..
  • git clone https://github.com/huxi/lilith.git
  • cd lilith
  • In build.gradle, replace the GPG key id with one of yours.
    allprojects { ext.'signing.keyId' = '740A1840' }
  • gradlew --no-daemon --stacktrace -Drelease=true -DignoreGit=true --recompile-scripts

Sorry for the convoluted steps necessary. I found no easier way so far.

Result

This causes the following error (stacktrace below was thrown by Gradle 2.9) in uploadPublished:

* What went wrong:
Execution failed for task ':lilith:uploadPublished'.
> Could not publish configuration 'published'
   > A POM cannot have multiple artifacts with the same type and classifier. Already have MavenArtifact de.huxhorn.lilith:zip.asc:asc:null, trying to add MavenArtifact de.huxhorn.lilith:zip.asc:asc:null.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':lilith:uploadPublished'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
    at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
    at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
    at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:77)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:47)
    at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:51)
    at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:28)
    at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:43)
    at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:170)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
    at org.gradle.launcher.Main.doAction(Main.java:33)
    at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
    at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
    at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:30)
    at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:129)
    at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
Caused by: org.gradle.api.artifacts.PublishException: Could not publish configuration 'published'
    at org.gradle.api.tasks.Upload.upload(Upload.java:66)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:227)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:585)
    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:568)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    ... 60 more
Caused by: org.gradle.api.InvalidUserDataException: A POM cannot have multiple artifacts with the same type and classifier. Already have MavenArtifact de.huxhorn.lilith:zip.asc:asc:null, trying to add MavenArtifact de.huxhorn.lilith:zip.asc:asc:null.
    at org.gradle.api.publication.maven.internal.DefaultArtifactPom.addArtifact(DefaultArtifactPom.java:65)
    at org.gradle.api.publication.maven.internal.DefaultArtifactPomContainer.addArtifact(DefaultArtifactPomContainer.java:52)
    at org.gradle.api.publication.maven.internal.deployer.AbstractMavenResolver.collectArtifact(AbstractMavenResolver.java:89)
    at org.gradle.api.publication.maven.internal.deployer.AbstractMavenResolver.publish(AbstractMavenResolver.java:80)
    at org.gradle.api.publication.maven.internal.deployer.BaseMavenDeployer.publish(BaseMavenDeployer.java:34)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyDependencyPublisher.publish(DefaultIvyDependencyPublisher.java:45)
    at org.gradle.api.internal.artifacts.ivyservice.IvyBackedArtifactPublisher$1.execute(IvyBackedArtifactPublisher.java:80)
    at org.gradle.api.internal.artifacts.ivyservice.IvyBackedArtifactPublisher$1.execute(IvyBackedArtifactPublisher.java:56)
    at org.gradle.internal.Transformers$4.transform(Transformers.java:137)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:61)
    at org.gradle.api.internal.artifacts.ivyservice.DefaultIvyContextManager.withIvy(DefaultIvyContextManager.java:39)
    at org.gradle.api.internal.artifacts.ivyservice.IvyBackedArtifactPublisher.publish(IvyBackedArtifactPublisher.java:56)
    at org.gradle.api.tasks.Upload.upload(Upload.java:64)
    ... 68 more


BUILD FAILED

I could really use some help fixing this as I don’t understand the root cause.

The above works as expected if you change the Gradle version back to 2.2.1.

This also shows that I need to perform more rigorous tests on the Gradle-RCs in the future. :slight_smile:

Thanks for the report, and for the reproducible test case. I can confirm this behaviour in the latest master: it looks like your configurations contain 2 different PublishArtifact instances that differ in name attribute, but have the same backing file and the same attributes as far as publishing to maven is concerned.

I’ve yet to confirm that this works in Gradle-2.2.1. Once I do, I should be able to determine the correct behaviour and implement a fix.

So digging a bit deeper, it looks like additional artifacts are present in the configuration in Gradle 2.9, and these are configured in a way that causes maven publishing to fail.

You can see the additional artifacts by adding a task like this to your build:

task printConfig << {
  ['archives', 'signatures', 'published'].each {
	def config = configurations[it]
	println "Configuration " + config.name
	config.artifacts.each {
	  println it
	  println it.file
	}
	println "------"
  }
}

You’ll also note that the same signature file name has been used for 2 different artifacts:

Signature lilith:zip.asc:asc:
/Users/daz/dev/gradle/playground/lilith/lilith/build/distributions/lilith-8.0.1.zip.asc
Signature lilith-8.0.1.zip.asc:zip.asc:asc:
/Users/daz/dev/gradle/playground/lilith/lilith/build/distributions/lilith-8.0.1.zip.asc

This leaves 2 mysteries:

  • Why are additional artifacts present in these configurations in Gradle 2.9?
  • Why is Gradle 2.9 generating duplicate signature artifacts for the same file name?

It would be great if you could dig deeper into your build and see if you can find an answer to the first question. That way we could make a simpler test case that could then be used to drive a fix for both issues.

Just some quick feedback so that you don’t think I’m just idling around… I tried to reproduce the issue in a small project but was out of luck so far, unfortunately. :frowning:

I’ll keep trying, though.

I finally pinpointed the problem. This commit contains the fix.

It seems that distZip is automatically included in the set of files signed by the signing plugin while it previously had to be added manually.

I have to admit that I was getting a little desperate about this problem…

Thanks for the update. Do you think it’s worth raising this change in behaviour as an issue?

I think the main issue was the very confusing error message and the fact that it only manifested itself while the task was executing, not during configuration where the duplicate entry was created. That’s also the reason I didn’t find it while testing RCs.

I’m not 100% sure if my assumption about automatic inclusion is correct.

I just know that:

  • The build works if I remove the line in the commit.
  • A signature is still being created for the file, as expected.

A really bad aspect of this issue is that I found the solution by randomly poking at things in my build file (OK, not entirely random… but you get my point…). That’s not in line with my usual Gradle user experience.

Ideally, a duplication shouldn’t be possible and an attempt should result in a good warning message during configuration, while the task should still work as if no such duplication attempt happened.