Artifactory Snapshot filename handling - snapshot

In our artifactory we have a snapshot repo defined to handle max 5 unique snapshots. We added -SNAPSHOT-.extension to the filename. SNAPSHOT gets also converted to timestamp. Build is done with gradle and artifact gets published with bamboo and artifactory plugin.
A file deployed to artifactory ...
inhouse-snapshots:com/example/project/subproject/trunk-SNAPSHOT/subproject-trunk-SNAPSHOT-79.amp
becomes ...
inhouse-snapshots:com/example/project/subproject/trunk-SNAPSHOT/subproject-trunk-20120321.154621-1-79.amp
This is fine and every build adds a new file with incremented build number, but the timestamp-number always stays 20120321.154621-1 so we have a file list like:
subproject-trunk-20120321.154621-1-79.amp
subproject-trunk-20120321.154621-1-80.amp
subproject-trunk-20120321.154621-1-81.amp
Anybody has a solution or suggestion for a another directory layout?

As you've correctly observed, the build number you've attach to the deployed file name is identified as a classifier; this is because Maven doesn't specify a build number with a non-unique snapshot.
Artifactory maintains the same combination of timestamp and build number for "batches" of artifacts and "bumps" the timestamp and build number when it detects a new "batch"; there are 2 ways in which Artifactory detects artifact "batches" for the purpose of converting non-unique to unique snapshots:
Artifacts are deployed in the exact order of: artifact (no classifier), POM, attached artifacts (with classifiers); The first ordinary artifact to be deployed after the a POM will create a new "batch"; hence providing a new timestamp and builder number.
Artifacts deployed with a matrix param of the key "build.timestamp" and a value of a millisecond-based epoch timestamp; Artifacts with same timestamp values will be associated under the same "batch".
You should either omit the build number from the deployed file and deploy it with a "build.timestamp" matrix param (to make Artifactory bump the "batch" on each new deployment) or deploy the files already with the unique snapshot.

I posted this solution: https://discuss.gradle.org/t/2-8-2-9-mavendeployer-doesnt-honour-uniqueversion-false-in-maven-uploadarchives/13370/8
The issue I had was multiple publications in the publishing section. The solution for me was to add the extra artifacts to the one publication. Then all of the items, api jar, source jar, api source jar and main jar have the same timestamp for a SNAPSHOT. This seems to take care of the build.timestamp automatically for me.
task apiJar(type: Jar) {
classifier = 'api'
from(sourceSets.main.output) {
include "com/company/app/dto/**"
}
}
task sourceJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task apiSourceJar(type: Jar, dependsOn: classes) {
classifier = 'api-sources'
from(sourceSets.main.allSource) {
include "com/company/app/dto/**"
}
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom.withXml {
asNode().appendNode('description', 'APP Sprint Boot App')
}
artifact apiJar
artifact sourceJar
artifact apiSourceJar
}
}
repositories {
maven {
credentials {
username = 'username'
password = 'password'
}
if(project.version.endsWith('-SNAPSHOT')) {
url "http://server:9081/artifactory/libs-snapshot-local"
} else {
url "http://server:9081/artifactory/libs-release-local"
}
}
}
}

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 executable binary as Maven SNAPSHOT in Artifactory

Asking as a relative newbie to repo terminology and semantics:
I have a gradle project that builds a Spring-Boot jar file, and then runs an InstallAnywhere project file to package the jar as an installer for a Windows service. I need to publish the executable installer as a SNAPSHOT. I am using the gradle artifactory plugin (not the artifactory-publish plugin, only because I'm following the example of sister project).
The artifact is being published to the Maven snapshot repo, but the "-SNAPSHOT" placeholder is not being replaced by a timestamp. When I add the original Jar file to the artifacts to publish, the Jar file gets a timestamp added, but the .exe still does not. Relevant gradle code follows, and project version is set to "1.0.0-SNAPSHOT" in gradle.properties, along with other shown artifactory configuration properties:
task buildInstaller {
inputs.files cleanJarName.outputs
outputs.file installerFile
doLast {
project.exec {
workingDir 'InstallKit'
commandLine "${System.env.INSTALLANYWHERE_HOME}\\build.exe", 'MyInstallAnywhereProject.iap_xml', '-nupd'
}
}
}
artifactoryPublish {
dependsOn buildInstaller
}
configurations {
published
}
artifacts {
published installerFile
}
artifactory {
contextUrl = project.artifactoryContextUrl
publish {
repository {
repoKey = project.artifactoryPublishRepo
username = project.artifactoryUser
password = project.artifactoryPassword
}
defaults {
publishConfigs('published')
publishBuildInfo = true
publishArtifacts = true
publishPom = true
publishIvy = true
}
}
resolve {
repository {
repoKey = project.artifactoryResolveRepo
username = project.artifactoryUser
password = project.artifactoryPassword
maven=true
}
}
}
So why won't Artifactory properly snapshot an .exe? We were going to see if it was a limitation of Maven repos only handling Java-related types (jar, war, ear, etc.). So we looked at creating another Artifactory repo for binary snapshots using the generic(?) repo type, but the configuration screens do not offer the snapshot options present in the Maven repo configuration.
SNAPSHOT (actually Integration Revision) terminology is mandated by repository layouts.
Since Artifactory enforces single-typed repositories you are correct that a Maven repo will not handle the versioning of an .exe file.
Using a generic repo is the correct path to take - but you need to define your own folder and file integration revision to have Artifactory pick up on it.

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.

Gradle script to copy maven artifact from local folder to another folder

In my project i want to copy certain artifact (war file) from maven repo to local folder in order to deploy. I tried using configurations object but i couldn't give specific groupid, artifact id, and version in that way
repositories {
mavenCentral() // or some other repo
}
configurations {
deploy
}
dependencies {
deploy "someGroup:someArtifact:someVersion"
}
task copyDeploy(type: Copy) {
from configurations.deploy
into "deploy"
}
You can find all of this and more in the Gradle User Guide (e.g. under "Working with dependencies") and the many samples in the full Gradle distribution.

Uploading multiple existing JARs to Maven repository with Gradle

I need to implement a Gradle task that will upload multiple existing JARs to the Maven repository.
The tricky part is that list of JARs is not known in advance. The way I want it to work is to dowload certain ".tar.gz" file first, untar it, then scan for JARs and upload them with some sort of naming convention (like use JAR names as artifactId's and version of the .tar.gz as version).
What would be the easiest way to do that with Gradle? Currently it is a simple bash script which searches for JARs and runs Maven deploy:deploy-file for each of them, but I need to incorporate that functionality in gradle build script.
Ideally, I need task like "deployJars" that would upload everything and depend on "downloadTarGz" task.
Update:
How about uploading POMs without any JAR attached to it? I need to generate several POMs that will depend on these dynamically detected JARs and upload them, too. "artifacts" requires me to specify file for upload.
To upload a jar via gradle you must declare that jar as a publish artifact and add it to a specific configuration using the artifacts closure:
apply plugin:'maven'
configurations{
allJars
}
artifacts{
allJars file("path/to/jarFile.jar")
}
now you can configure the dynamically created uploadAllJars task:
uploadAllJars {
repositories {
mavenDeployer {
repository(url: 'http://localhost:8081/artifactory/acme') {
authentication(userName: 'admin', password: 'password');
}
}
}
The problem is that you want to upload multiple artifacts. To achieve that you need some more dynamic in your build script. The dynamic creation of publishartifacts for all discovered jars can be wrapped in a task. In my example the discoverAllJars task simply looks in a specified folder for jar files. Here you need to implement your own logic to lookup the jars in your tgz archive.
group = "org.acme"
version = "1.0-SNAPSHOT"
task discoverAllJars{
ext.discoveredFiles = []
doLast{
file("jars").eachFile{file ->
if(file.name.endsWith("jar")){
println "found file ${file.name}"
discoveredFiles << file
artifacts{
allJars file
}
}
}
}
}
To be able to upload multiple artifacts within the uploadAllJars task you have to use pom filter. For details about pom filter have a look at the gradle userguide at http://www.gradle.org/docs/current/userguide/maven_plugin.html#uploading_to_maven_repositories
Since we moved the configuration of the published artifacts into the execution phase of gradle we must configure the uploadAllJars in the execution phase too. Therefore I'd create a configureUploadAllJars task. Note how we reference the jar files discovered by using 'discoverAllJars.discoveredFiles':
task configureUploadAllJars{
dependsOn discoverAllJars
doLast{
uploadAllJars {
repositories {
mavenDeployer {
repository(url: 'http://yourrepository/') {
authentication(userName: 'admin', password: 'password');
}
discoverAllJars.discoveredFiles.each{discoveredFile ->
def filterName = discoveredFile.name - ".jar"
addFilter(filterName) { artifact, file ->
file.name == discoveredFile.name
}
pom(filterName).artifactId = filterName
}
}
}
}
}
}
Now you just need to add a dependency between uploadAllJars and configureUploadAllJars:
uploadAllJars.dependsOn configureUploadAllJars
This example uses the same group and version for all discovered jar files and the jar name as artifactId. you can change this as you like using the pom filter mechanism.
hope that helped,
cheers,
René

Resources