Gradle maven deployer versioning - maven

We are using Gradle + Maven Plugin to upload jar files to our artifact repository using the following piece of code:
uploadArchives {
repositories {
mavenDeployer {
repository(url: <our maven repo URL>)
pom.groupId = 'group1'
pom.version = '???'
pom.artifactId = 'artifact1'
}
}
}
We set a hook in our CI server that triggers the upload with every push to the master Git repository. I have two questions:
Is that a good idea to automatically upload the jar files on a commit? What's the downside?
How can I give the uploaded jars an automatic new version number, like the latest version plus one? Is that possible to list all the availale versions of an artifact from a maven repo?

It's basically not a bad idea however You need to consider how the dependency is specified for the given artifact - e.g. if some backward incompatible changes were introduced other clients of the uploaded artifact may have problems. So specifying the dependency with + may be problematic and manually switching the version after every release could be tiring. It's good idea to work out why you'd like to upload artifact after every build? Maybe consider uploading artifacts only from a certain branch
Every CI server should pass a build number as a env variable (or system property) to the artifact being built. It's good idea to use this number in automatic versioning. It is possible to download the versions from the repository, but it requires additional work to be done. Download maven-metadata.xml (e.g. this one), parse it, get the latest version and you are almost done.

Related

tell maven to get JAR dependency from given URL

Unfortunately, my project has an external dependency that was never published to any Maven repository. The only way I can get it is by direct download from github (they pushed the binary to github).
One (bad) way is to download the jar manually and commit/push it to my code repository (git). It wouldn't help me to manually deploy this artifact in my local binary repository because I share this project with external contributors that cannot access my private binary repo.
I wonder if maven has a better way to handle this? (Given that I can't upload the artifact to my repo or public repo).
I know that npm allows getting some dependencies from URL. Does maven support it as well?
AFAIK there is no nice way to handle this. You could
Write a script that downloads the jar and installs it in your local Maven repository. This script could be shared through your code repository.
Include downloading and installing the artifact into the Maven build process (by writing a Maven plugin or using the antrun plugin)
Set up a nexus in the cloud that everyone in your team can access.

Can I avoid Maven deployed war version with timestamp in Archiva?

In out project we are using using deployed war file in /archiva-2.2.0/repositories/internal/com/xyz/1-SNAPSHOT/proj-1-20160204.122021-15.war path using shell script to copy to jboss. However finding the latest build timestamp and build number is very difficult. Is there a way to avoid using timestamp while storing it in archiva like proj-1-SNAPSHOT.war?
I have already read about <uniqueVersion>false</uniqueVersion> whcih is not supported in maven 3.
I am using archiva-2.2.0, maven-3.3.9.
Maven repositories wasn't designed to distribute deployable components, your continuous integration environment should take care of this. Jenkins has eg Archive Artifacts (native) and Copy Artifact Plugin which you can use to store and recover binaries in your pipelines.
But you can workaround this behavior changing the version of the war to a stable one - removing the -SNAPSHOT suffix. This will lead you with a predictable URL.
I am posting this as it is a new finding, if I wget http://xx.xx.xx.xx:8083/repository/internal/com/xyz/1-SNAPSHOT/proj-1-SNAPSHOT.war. I get the latest deployed artifact in the archiva repository. So archiva does a 302 redirect to point to url of http://xx.xx.xx.xx:8083/repository/internal/com/xyz/1-SNAPSHOT/proj-1-20160204.122021-15.war location and downloads the latest build. I am not sure if this works for other repositories like nexus or artifactory etc.
Ofcourse I will need a cron job to periodically clear of the stale snapshot artifacts.

why does maven check for updates when I have specified a version?

I have trouble understanding, why maven has to check for updates each time we build a project.
The pom has specific version mentioned for each dependency. Once those versions are downloaded to the local repo, then maven can use that local copy to build the project. So why does maven have to check for updates when we build the project each time other than just using the local copy?
a side question.
can a maven artifact be changed after releasing it to a repo under a specific version?
As per Maven, an artifact mainly can be of two types - a RELEASE one and a SNAPSHOT one. RELEASE dependency(eg: 1.0.1, 2.3.0 etc) of an artifact is a source of truth. Means 1.0.1 version of a jar (say test.jar) will always be the same always. We will release artifacts to remote repository, whenever the product matures or after a sequence of bug fixes.
On the other hand, a development is on going in a project, then specified its version number as SNAPSHOT(eg: 2.0-SNAPSHOT, 1.1-SNAPSHOT etc).
Say if we specified test-2.0-SNAPSHOT.jar as dependency in our project pom. If we look at the remote repository (Nexus, archiva etc), we can see that it is not saved as version 2.0-SNAPSHOT rather it will be saved artifact version as date-timestamp-buildnumber format, the date-timestamp at which the artifact was built and uploaded to remote repo. (eg: test-2.0-20150105082634.jar)
So when ever the development team does the fix for an issue on a daily basis the updated jar with date timestamp will be in uploaded to the remote repo. So it is necessary for maven to do look up for the latest date timestamp of SNAPSHOT artifacts. Maven does this by maven-metadata.xml file in the artifact directory in the repo.
Hope this clarifies your query. Let me know, if you need any clarifications

Automated release to Maven Central with Gradle

I'd like to upload my jar to the Maven Central repository using gradle uploadArchives and use it in other projects as a dependency.
I've followed this nice tutorial with the result that my jars are uploaded to Sonatype Nexus (see screenshot below).
The 0.1 version of my jar is available; the line
dependencies {compile 'eu.matthiasbraun:Utils:0.1'}
works just fine in the build.gradle file of my dependent project. I released the 0.1 version by clicking the Close and the Release buttons seen in the screenshot. After that I commented on the Jira ticket I had created here and was told that central sync would run every two hours.
It was my understanding that if I now wanted to release the 0.2 version of my jar, I simply would do gradle uploadArchives and change the line in build.gradle` of my dependent project to
dependencies {compile 'eu.matthiasbraun:Utils:0.2'}.
Yet, when I gradle build my dependent project (after two hours) I got the error that the dependency could not be resolved.
Here's my complete build.gradle which uploads my jar to Sonatype Nexus: link.
How can I automate the release of jars to Maven Central using Gradle?
I've used the nexus-workflow gradle plugin to automate the releasing of repositories.
I put this at the top of the build.gradle of my project I want to release:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.adaptc.gradle:nexus-workflow:0.6'
}
}
apply plugin: 'nexus-workflow'
Additionally I put these three properties in ~/.gradle/gradle.properties
oss-releases.username=mySonatypeUsername
oss-releases.password=mySonatypePassword
oss-releases.url=https://oss.sonatype.org/index.html#stagingRepositories
When I want to push a release to Maven Central, I first upload the jars to Nexus using gradle uploadArchives and then I do gradle nexusStagingRelease. This closes and releases all my open repos on Nexus.
Edit:
I also found this plugin by Benjamin Muschko which seems to be an alternative to the plugin described above. I didn't try it yet, though.
Gradle Nexus Staging Plugin can be used to automatize closing the repository and promote/release artifacts to Maven Central.
It has to be added to your project:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.1"
}
}
apply plugin: 'io.codearte.nexus-staging'
and configured:
nexusStaging {
packageGroup = "org.mycompany.myproject"
stagingProfileId = "yourStagingProfileId" //optional, but reduce number of calls to Nexus
}
After the artifacts were uploaded (with uploadArchives or any other way) it is enough to call:
./gradlew closeRepository promoteRepository
If a synchronization with Maven Central was enabled the artifacts should automatically appear into Maven Central within several minutes.
More information (including the ways how credentials can be provided) in that blog post or on the project webpage.
Disclaimer. I am the author of this plugin.
The screenshot shows that you have not yet released you library. You have only staged it to OSSRH. What you need to do next is to
Close the staging repository by pressing the 'Close' button, this signals to Nexus that nothing else is expected to be added to the staging repository
verify the files in the content are ok
if you are happy with everything - release the components to Central by pressing the 'Release' button,
or if you are unhappy with it press 'Drop' button to delete the staging repo and start from scratch
waiting till everything is synced to Central from OSSRH (takes up to an hour or a bit more depending on your timing)
Btw. if you can automate this on the command line with the Nexus Staging Maven Plugin or the Ant Tasks. And you can wrap the Ant tasks and use them in Gradle. More info about all this is in the staging chapter of the Nexus book.

deploy on nexus artifacts with Snapshot policy but without SNAPSHOT string in version

apparently my Nexus is rejecting every deploy I throw at him if the artifact has not -SNAPSHOT in the version.
Data:
name of the failing artifact: entando-core-engine-experiment-bundles_with_bootstrap.jar where experiment-bundles_with_bootstrap is the version as in the version element of the pom.xml
hosted repository policy on my Nexus: Snapshot, allow redeploy and so on (classic conf for snapshots)
deployer: Jenkins 1.481
same Jenkins job, but entando-core-engine-SNAPSHOT.jar ---> SUCCESS
I need this naming convention because I'm building one of the several experiments we run internally, as opposite to the canonical develop branch which produces a proper entando-core-engine-SNAPSHOT.jar
Any advice?
I'm totally lost.
The thing is that usually your Nexus is configured not to allow a redeployment of a release. A release from Maven point of view is an artifact where it's version it NOT -SNAPSHOT. In contradiction a SNAPSHOT is intended to be deployed several times into nexus.
This sounds like you don't using the release plugin of Maven nor the Release PLugin of Jenkins.
Nexus is a repository manager that uses different repository formats, with the main format being the Maven repository format. Changing the names of artifacts on the server is not possible since it violates the format. They have to be located in the directory structure established by groupId, artifactId and version and use the artifactId-version-classifier.packaging for the file names.
If you need a different file name on the server you have to look at a different repository format (bad idea). If you need the filename on the client just download from the correct name and rename..

Resources