Multiple artifacts issue with deploying zip to nexus - gradle

My program outputs a zip and I want to deploy this zip to the nexus repository. I am using gradle as build system.
Fragment of my configuration:
class DestinationFileTask extends DefaultTask {
File destFile;
}
task generate(type: DestinationFileTask) {
destFile = file('output/file.zip')
}
artifacts {
output generate.destFile
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: "url")
pom.version = "1.01-SNAPSHOT"
pom.artifactId = "ID"
pom.groupId = "com.test.test"
}
}
}
When I am executing gradle uploadArchives I am receiving this error:
> Could not publish configuration 'archives'
> A POM cannot have multiple artifacts with the same type and classifier. Already have MavenArtifact ID:zip:zip:null, trying to add MavenArtifact ID:zip:zip:null.
Even when I try to do this for the first time.

I ran into the same issue while working on Gradle upgrade:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':registry:uploadArchives'.
> Could not publish configuration 'archives'
> A POM cannot have multiple artifacts with the same type and classifier. Already have MavenArtifact registry:zip:zip:null, trying to add MavenArtifact registry:zip:zip:null.
Gradle upgrade it self has nothing to do with the error its more related to the plugins you are using.
The error is really misleading and there is not much info on Google about it as well.
But it turns out that the cause of this error is Maven trying to upload artifact on top of the other one.
So first of all check what packaging tasks you are executing, in my case:
task ':registry:bootDistTar',
task ':registry:bootDistZip',
...
task ':registry:distTar',
task ':registry:distZip',
The workaround to fix it is to change the classifier (in my case for spring boot app):
bootDistTar {
classifier = 'bootTar'
}
bootDistZip {
classifier = 'bootZip'
}
Hope this will help for someone else as it was quite hard to figure out.
Github issue where I found the workaround.

Related

Artifactory gradle and properties mutation by artifactoryPublish task DSL

My problem with build-info-extractor gralde plugin for artifactory
Source code with example for reproduce problem: https://github.com/lavcraft/gradle-artifactory-build-info-extractor-problems
Configure environment – artifactory_user artifactory_password artifactory_contextUrl
Run ./gradlew build aP
See jar artifacts properties in you artifactory instance
I expect, that this example (see below) works perfectly
artifactoryPublish {
properties = ['aa':'aaa']
properties {
nebula '**:**:**:*#*', 'not_added_prop':'sub0'
}
}
see sub0/build.gradle in github project
But it does not work. What is wrong with my example?
I think I found the cause of this issue.
Here's the artifactory closure configured in the build.gradle file, in the project you shared:
artifactory {
contextUrl = project.findProperty('artifactory_contextUrl')
publish {
repository {
repoKey = 'libs-snapshot-local'
username = project.findProperty('artifactory_user')
password = project.findProperty('artifactory_password')
}
defaults {
publications('nebula')
publishConfigs('archives')
publishIvy = false
properties {
nebula '*:*:*:*#*', 'want_to_add':'but not' // add only to *.pom artifacts. Why?
mavenJava commonProperties, '*:*:*:*#*'
}
}
}
}
As you can see above, the closure includes one publication (nebula) and one configuration (archives).
Running the build script as is prompts the following deployed artifacts:
$ gradle clean artifactoryPublish
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub0/0.1.1-SNAPSHOT/sub0-0.1.1-SNAPSHOT.jar
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub0/0.1.1-SNAPSHOT/sub0-0.1.1-SNAPSHOT.pom
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub1/0.1.1-SNAPSHOT/sub1-0.1.1-SNAPSHOT.jar
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub1/0.1.1-SNAPSHOT/sub1-0.1.1-SNAPSHOT.pom
Now, if you comment out the publication as follows:
//publications('nebula')
publishConfigs('archives')
You can the following:
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub0/0.1.1-SNAPSHOT/sub0-0.1.1-SNAPSHOT.jar
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub1/0.1.1-SNAPSHOT/sub1-0.1.1-SNAPSHOT.jar
So it looks like both the archives configuration and the nebula publication contribute the same two artifacts above.
Since "want_to_add" property is configured on the nebula publication (and not on the archives publication), the 2 jars contributed by the configuration don't get the property.
A simple fix for this is issue is to remove the archives configuration:
publications('nebula')
//publishConfigs('archives')
Alternatively, if for some reason you do want to have both the configuration and publication, you can add the property to your configuration as well. Here's how you do this:
properties = ['want_to_add': 'but not']
So the full closure, with both the publication, configuration and properties for both is this:
defaults {
publications('nebula')
publishConfigs('archives')
publishIvy = false
properties = ['want_to_add': 'but not']
properties {
nebula '*:*:*:*#*', 'want_to_add':'but not' // add only to *.pom artifacts. Why?
mavenJava commonProperties, '*:*:*:*#*'
}
}
You can read more about this here:
https://www.jfrog.com/confluence/display/RTF/Gradle+Artifactory+Plugin

Gradle: publish an artifact with a subset of files/dependencies of a project

I am lost in all these plugins :(
What I have so far, looks something like this:
artifactory {
contextUrl = artifactoryUrl
publish {
repository {
repoKey = project.repo
username = artifactoryUser
password = artifactoryPassword
maven = true
defaults {
publications('mavenJava')
}
}
}
version = "${majorVersion}${buildNumber}${snapshot}"
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourceJar {
classifier = 'sources'
}
}
}
}
I am sorry, I did write this myself, but, mostly by copying and pasting things from various examples I found on the web, so I am not sure what this is actually doing :(
Surprisingly, this works: I can do gradle artifactoryPublish, and uploads a pom file and two jars (classes and sources) to artifactory.
But, I need to modify it, so that I can publish a subset of the project as a different artifact, and only include the dependencies that it requires.
I managed to build a jar file:
task utilJar(type: Jar) {
from sourceSets.main.output.classesDir
include '**/util/*.class'
baseName 'basic-util'
}
I also defined a Configuration with a subset of dependencies:
configurations {
util
}
dependencies {
util "org.apache.commons:commons-lang3:3.4"
util "com.google.guava:guava:18.0"
}
artifacts {
util utilJar
}
This is where I get stuck. How do I get this new artifact published?
I tried following the same strategy:
publishing {
publications {
mavenUtil(MavenPublication) {
from components.java
artifact utilJar {
classifier = 'util'
}
}
}
}
artifactory {
defaults {
publications('mavenUtil')
}
}
(this is in a subproject, so I need it do be incremental)
This does not work:
Could not find method defaults() for arguments [build_8axxghkylu3559p5lal6spy1u$_run_closure7$_closure11#38abcbd4]
But, even if it did, it would still be not be quite what I need, because I don't know how I could then publish a particular artifact: the only way I could ever publish anything at all is gradle artifactoryPublish, but that does not ask me which artifacts to publish. Will it publish everything every time?
As you can see, I am hopelessly lost here :(
Could someone with a clue please show me the light?
UPDATE So, I removed the last artifactory closure from the build, and now I not getting the error, but still can't get it to do what I need.
My artifactory seems to be not in good mood right now, so I am publishing locally.
gradle publishToMavenLocal creates a single artifact as before, but adds my new "-util" jar to it. This is not at all what I want. I need a new, separate artifact, with that jar file, and its own set of dependencies.
Here: https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:repositories I found a suggestion, that "The created task is named “publish«PUBNAME»PublicationTo«REPONAME»Repository”". This does not seem to to be true, because gradle publishUtilMavenPublicationToMavenLocalRepository (with all the case variations I could think off) says that there is no such task. :(
Have you tried using the set me up feature? It available for all version of Artifactory. It should provide a good starting point to configure you gradle project to work with Artifactory.
Specifically for Gradle it can assist you with generating the relevant configuration according to the repositories you wish to resolve / publish from / to, defining the relevant dependencies to install the jfrog plugin etc.

How to use gradle Artifactory plugin in gradle subproject

I have a multi-project gradle build wherein one of the subprojects is applying the Artifactory plugin (version 4.2.0), and configuring the contextUrl and resolve repoKey.
It sets up a simple configuration and dependency entry, and then has a copy task to retrieve the dependency as a zip file and extract it into a directory.
However, when the copy task runs, I get the error below. What am I doing wrong? Is this a problem with the Artifactory plugin, or gradle, or...?
The problem does not appear to be related to whether or not this is a subproject. I get the same error if I remove the multiproject configuration and run the task from the subproject directory.
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\Users\hoobajoob\project\subproject\package.gradle' line: 36
* What went wrong:
A problem occurred evaluating project ':subproject'.
> Could not resolve all dependencies for configuration ':subproject:runtimeDep'.
> Cannot resolve external dependency company.com:artifact-id:1.0.0 because no repositories are defined.
Here are the contents of subproject/package.gradle (Artifactory url/user/password properties are in a gradle.properties file for the subproject):
plugins {
id "com.jfrog.artifactory" version "4.2.0"
}
artifactory {
contextUrl = "${artifactory_contextUrl}"
resolve {
repository {
username = "${artifactory_user}"
password = "${artifactory_password}"
repoKey = 'some-repo'
}
}
}
configurations {
runtimeDep
}
dependencies {
runtimeDep 'company.com:artifact-id:1.0.0#zip'
}
ext.destination = null
task getDependencies(type: Copy) {
from zipTree { configurations.runtimeDep.singleFile }
into ".artifacts/runtime"
}
The root project build script is empty except for the wrapper task. Below is the settings.gradle file:
include 'subproject'
rootProject.children.each { project -> project.buildFileName = "package.gradle" }
While the task setup in my question is different, this appears to be the same symptom as described in this other SO question.
The problem seems to be related to the fact that the Artifactory plugin will not perform dependency resolution until gradle's execution phase. I had assumed that defining the argument to the zipTree step in the getDependencies task with a closure would have the effect of deferring the dependency resolution until that phase.
But, for this to be deferred by the copy task, I need to define the from configuration of the getDependencies task as a closure, and include the zipTree operation in that closure.
It's the difference between:
from zipTree { configurations.runtimeDep.singleFile } // doesn't work
...and
from { zipTree( configurations.runtimeDep.singleFile ) } // works
Making this change gets the resolve working (with no required maven repositories block).
Another solution is to drop the Artifactory configuration altogether (which I can do in this case because I do not need to utilize anything unique to Artifactory) and use the traditional gradle repositories block, as described in the other SO question and by crazyjavahacking. Doing this makes the build script shorter, and I can leave the zipTree step configured as it was originally written:
repositories {
maven {
url "${artifactory_contextUrl}/repo-key"
}
}
configurations {
runtimeDep
}
dependencies {
runtimeDep 'company.com:artifact-id:1.0.0#zip'
}
ext.destination = null
task getDependencies(type: Copy) {
from zipTree { configurations.runtimeDep.singleFile }
into ".artifacts/runtime"
}
As the Gradle print to the console:
You did not define repositories{} block and so it does not know how to download declared dependency.

Getting spring boot jar files through gradle

The spring framework wants users to use dependency tools to download the framework, so I am trying to use gradle. I got this sample from their website http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto
buildscript {
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.BUILD-SNAPSHOT")
}
}
apply plugin: 'java'
apply plugin: 'spring-boot'
jar {
baseName = 'root'
version = '0.0.1-SNAPSHOT'
}
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
I saved this to a file called build.gradle. Then in the CMD I went to the directory where the build.gralde file is located and type:
gradle build
It seemed to run fine but towards the building it's not working, here is the last logs I got from the command prompt:
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:jar
:bootRepackage FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':bootRepackage'.
Unable to find main class
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug
option to get more log output.
BUILD FAILED
Total time: 9.664 secs
I don't understand this "> Unable to find main class". I only want to get all the jar files and put them inside WEB-INF/lib of my eclipse projects. I am extremely new at gradle. What should I do?
It's not really clear to me, acoording to your comments, what are you trying to achieve, if you don't have a project sources, but for some reason wants to download dependent libraries. Gradle doesn't work this way, all the libraries are dowloded on demand, that means, they are dowloaded then you, for example, try to build your source files.
The exception you get, means, that gradle spring boot plugin's task bootRepackage Didn't find a main class in your project. This main class is mandatory for this task, since the task creates a standalone executable jar.
Sure, it is possble to dowload deps by custom task, like:
task getDeps(type: Copy) {
from sourceSets.main.runtimeClasspath
into 'runtime/'
}
But it seems, that you don't properly understand, how does it work. You should try to read gradle user guide first and let gradle to build your project for you, but not just combine some libs.

Gradle's publishToMavenLocal task is not executed correctly

I'm trying to create a gradle based multi-module project. There is also an project that contains different gradle scripts that enables pluggable build configurations. One of those scripts is for publishing artifacts to maven repository. This is the content of that script:
apply plugin: 'maven-publish'
configure(subprojects.findAll()) {
if (it.name.endsWith('web')) {
publishing {
publications {
mavenWeb(MavenPublication) {
from components.web
}
}
}
} else {
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
}
}
build.dependsOn publishToMavenLocal
This script is included in the build gradle file of other project.
apply from: '../../food-orders-online-main/artifact-publish.gradle'
When I run build task it always shows that publishToMavenLocal task is up to date and I cannot find the artifacts in the local repository. Am I doing something wrong?
By adapting answer from here, it works for me.
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
repositories {
mavenLocal()
}
}
I think this could be a manifestation of a bug with gradle, that modules can lose the publishMavenJavaPublicationToMavenLocal task when they are depended upon in a certain way.
If gradle determines that there is no publishMavenJavaPublicationToMavenLocal task for a module then the publishToMavenLocal task will always report that it is up to date.
The specific case I have found occurs in a multimodule setup, with multiple levels of nested modules. It can be summarised as follows, where shared:domain loses its publishMavenJavaPublicationToMavenLocal when depended upon by A
root
root gradle build file
->A
own gradle build file with dependency on shared:domain
-> shared
gradle build file for shared modules
-> shared:domain
-> shared:B
I have created a small example project demonstrating this behaviour available here - https://github.com/piersy/Gradle2MavenPublishBug
I have also logged a bug with gradle here - http://forums.gradle.org/gradle/topics/the-publishmavenjavapublicationtomavenlocal-task-disappears-from-a-project-when-that-project-is-depended-upon-in-a-specific-way
For now the workarounds I have found are to
Remove A's dependency on shared:domain
Make A a submodule with its configuration specified in its parent module build file
Give shared:domain its own gradle build file

Resources