Gradle Nexus and FlatDir deployment without java-, ear- or war-plugin - gradle

I have a multi-project gradle (version 2.1!!) build consisting of non-java projects.
I would like to deploy the generated artifacts (.tar.gz files) to a Nexus and also to a directory.
Currently I define the repositories in the root build.gradle in the repositories block and also again for each sub-project in a repositories block inside the subprojects in the root build.gradle file.
I apply the base plugin to the root project and the maven-publish plugin to all subprojects that have artifacts to be deployed.
I tried to follow the instructions here:
https://docs.gradle.org/2.1/userguide/publishing_maven.html
https://docs.gradle.org/2.1/dsl/org.gradle.api.publish.maven.MavenPublication.html
https://discuss.gradle.org/t/how-to-have-multiple-uploadarchives/19381/3
How can I make uploadArchives dependent on another task?
and a few more...
but nothing worked. :-(
Here's what I do:
...
# apply the maven-publish plugin only to sub-projects that produce artifacts that should be uploaded.
apply plugin: 'maven-publish'
publishing {
publications {
tarFiles (MavenPublication) {
artifact compressTar
}
}
repositories {
add rootProject.repositories.fsShare
add rootProject.repositories.nexusDeploy
}
}
...
The compressTar is my custom Tar task that creates the artifacts that I want to upload.
When I execute ./gradlew publishTarFilesPublicationToNexusDeployRepository I get the following error:
Execution failed for task ':mySubProject:publishTarFilesPublicationToNexusDeployRepository'.
> Failed to publish publication 'tarFiles' to repository 'nexusDeploy'
> Failed to retrieve remote metadata myRootProject:mySubProject:0.0.0.0-SNAPSHOT/maven-metadata.xml: Could not transfer metadata myRootProject:mySubProject:0.0.0.0-SNAPSHOT/maven-metadata.xml from/to remote (https://myProject.nexus.url:443/nexus3/repository/builds/): Could not get resource 'myRootProject/mySubProject/0.0.0.0-SNAPSHOT/maven-metadata.xml'
When I execute uploadArchives, the task succeeds, but nothing is uploaded anywhere and from the output it looks like the uploadArchives task is only executed for sub-projects that didn't get the maven-plugin applied.
What is the right way to do this? Which plugins should I apply when/where?

Apparently there were two un-related "problems at work" here.
Problem 1): I was not able to publish to Nexus and got a Failed to retrieve remote metadata-error:
Answer 1): I was trying to publish a "SNAPSHOT" to a repository that was configured not to accept "SNAPSHOT" build. Renaming the build version from 1.2.3.4-SNAPSHOT to anything else (e.g. 1.2.3.4-SNAPSHOT-dev or more reasonable 1.2.3.build4`) worked fine.
Problem 2) Publishing to 'flatDir' repository didn't work. The maven-publish plugin didn't create the publish task for it.
Answer 2) To use maven-publish to publish to a directory, flatDir apparently is not recognized as repository the maven-publish plugin can publish to. Defining the 'directory' repository as follows worked fine:
maven {
name "fsShare"
url "/share/pkg"
}

Related

Get full artifact name generated by gradle

I'm publishing an artifact using maven-publish.
When I'm pushing a release artifact, the resulting artifact version is the same as the project version itself. For example if gradle.properties has version=1.2.3, the artifact would be something like foo-1.2.3.zip.
When I run a SNAPSHOT publish, the resulting artifact will include additional information in the version. For example version=1.2.4-SNAPSHOT gives foo-1.2.4-20220427.094127-1.zip. The additional information would appear to be the time and date to avoid clashes, I assume.
Is there anyway I can access this full artifact name in my gradle scripts?
If you don't specify the artifact names explicitly like this for example
publishing {
publications {
maven(MavenPublication) {
groupId = 'org.gradle.sample'
artifactId = 'library'
version = '1.1'
from components.java
}
}
}
Then gradle will use the defaults that are taken from your build.gradle, gradle.properties and the module directory names.
I'm not sure if there's a way to configure the mavenPublish plugin to print out the maven artifact upon publishing, but you can look in your ~/.m2 directory to see what exactly has been published to your local if you run ./gradlew publishToMavenLocal
I'm also thinking you could create a custom task to print out the group, artifact and version, something like this in the build.gradle of your project you are publishing:
project.task('getMavenCoordinates') {
doLast {
println "Maven Artifact: ${project.group}:${project.name}:${project.version}"
}
}
project.task("publishToMavenLocal").dependsOn("getMavenCoordinates")
If you wanted to configure the task to run after a different maven-pubish task, just change it accordingly! But something like that could help achieve what you want.

Publish reusable gradle tasks

I would like to publish some common parts of build.gradle file to be reusable in different projects (using apply from: url_to_file construction). To achieve this I've created a project called gradle-common that contains those common build files, with this build.gradle file:
group 'org.example'
version '0.1.0'
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
artifact source: file('files/first.gradle'), classifier: 'first'
}
mavenJava(MavenPublication) {
artifact source: file('files/second.gradle'), classifier: 'second'
}
}
repositories {
mavenLocal()
}
}
Files after publishing in maven repository there are files like:
gradle-common-0.1.0-first.gradle
gradle-common-0.1.0-second.gradle
And my question is: how can I remove version number from published artifacts and the classfier? For me ideal files would be:
first.gradle
second.gradle
There are many different answers to your question, but I think you are trying to create something that a plugin usually does without creating a plugin.
The best way to add functionality to multiple gradle projects is to create a plugin. You can also leverage Rules which this simple tutorial doesn't show, but you can inspect some of the gradle native plugins, such as maven-publish.
To answer your question, it is not possible to publish an artifact to a maven repository without a version. You have to download it with a version (you can use my-artifact:1+ to download the latest) and then strip the version yourself.
I am also wondering how are you planning to include these files to your specific gradle files. You won't be able to use them as dependencies, since the dependency resolution happens after the scripts are read. If you are downloading them somehow before the script runs, then you probably don't need a maven repository for that.

Can I Publish Multiple Files To Nexus From Gradle In One Go?

I am using a closed source vendor application that occasionally sends me updates of jars in a zip file.
I want to refer to the zip in the Gradle build, unzip it and publish all the jars within it to my Nexus repo. I am assuming that they all have the same GroupId and that the name and version can be inferred from the file name itself.
Whilst testing out my script, I would rather not publish to Nexus and have to delete lots of test artifacts so I am using a flatDir repo for now.
So far I have this
apply plugin: 'maven'
configurations {
zipArchives
}
uploadResultArchives {
repositories {
mavenDeployer {
flatDir(dirs: 'mvn')
pom.groupId = 'com.stackoverflow.example'
}
}
}
artifacts{
zipArchives file: file('unzipdir/api-1.2.34.jar')
}
This suffers from multiple problems.
It requires me to manually add the files to the artifacts list
It creates a pom with dependencies from the rest of my project instead of a pom with no dependencies
I haven't parsed out the versionId yet
This solution looks like the versionId is going to be the same for all
Is there a better way to approach this?

Use gradle to upload jar to local Maven repository

This question has been asked several times, but somehow I don't get this to work. Gradle is a great tool, but its documentation is anything but great. No examples make it almost impossible to understand for someone who doesn't use it on a daily basis.
I am using Android Studio and I want to upload my module output jar to my local Maven repository.
apply plugin: 'java'
dependencies {
compile 'com.google.http-client:google-http-client-android:1.18.0-rc'
}
apply plugin: 'maven'
configure(install.repositories.mavenInstaller) {
pom.project {
groupId 'com.example'
artifactId 'example'
packaging 'jar'
}
}
When I start a build in Android Studio, I can see on the Gradle tab that
:install
is invoked. I also get a new jar in my build folder, but that jar is not uploaded to Maven. [The Maven repo exists and the Google appengine gradle plugin uploads its jar from another module of the same project just fine.]
What am I missing?
I suspect the problem is that you are only editing the POM (via pom.project), instead of configuring the actual Maven coordinates used for installation. Try the following instead:
// best way to set group ID
group = 'com.example'
install {
repositories.mavenInstaller {
// only necessary if artifact ID diverges from project name
// the latter defaults to project directory name and can be
// configured in settings.gradle
pom.artifactId = 'myName'
// shouldn't be needed as this is the default anyway
pom.packaging = 'jar'
}
}
PS: The samples directory in the full Gradle distribution contains many example builds, also for the maven plugin.
Peter N is CORRECT in the comments of the accepted answer, which works, but shouldn't be the accepted answer.
You should have this in your build.gradle file
apply plugin: "maven"
Then you can just do a
$ ./gradlew install
Or use the built-in task
$ ./gradlew publishToMavenLocal
Both methods install the artifacts in $HOME/.m2/com/example/example/version

Gradle prefer repository on duplicate entries

I have a build tool thats tied the version to the SCM. I can't set the version of a jar when I build it locally. If someone were to change what I'm working on locally it would push the version number (which I can get), but when I publish to my local repo (Ivy) Gradle seems to prefer the external repo.
build.gradle
repositories {
mavenCentral()
ivy {
url "${System.properties['user.home']}/.ivy2/local/"
layout "pattern", {
artifact "[organization]/[module]/[revision]/[artifact](-[classifier]).[ext]"
ivy "[organization]/[module]/[revision]/ivy.xml"
}
}
ivy {
url "https://repo/"
layout "pattern", {
artifact myPattern
ivy myIvyPattern
}
}
}
Without changing the build for the jar that I'm editing. How can I have gradle always prefer the local repo? I have a feeling that resolutionStrategy might be the best way, but I don't know how accomplish this.
Edit 1
To help clarify, Artifactory has a jar (published by jenkins) with version 1.2.3. I have a jar that I build locally that saves into my local repository as 1.2.3. When I build a project having both repositories in my repository closure (with my local one on top) Gradle seems to pull in the one from Artifactory.
Edit 2
Dependency definition
dependencies {
compile ('company:project:1.2.+')
}
I don't really understand what you are saying, but Gradle searches repositories in their declared order, and picks the first matching module that it finds (as least as long as fixed versions are used).

Resources