Downloading only a POM file from Maven/JFrog repository - maven

I would like to fetch/download only! a POM file from a properly published (with metadata) artifact.
It is easy to write a task downloading jars only
task getArtifacts(type: Copy) {
from configurations.myConf
into myWorkingDir
}
and setting the transitive flag to false for myConf(iguration).
But how to download the related POM files only!
The real reason for this is: I obfuscate the downloaded jars, then deploy them back to the repository as an obfuscated version. But I would like provide the pom metadata for the obfuscated artifacts … just using artifacts.add(xxx.pom) before publicizing.
Maybe you know any other idea how to implement the publication of obfuscated jars with metadata in Gradle?

You can use an ArtifactResolutionQuery to manually resolve artifacts of a specific type:
def result = dependencies.createArtifactResolutionQuery()
.forModule('group', 'name', 'version')
.withArtifacts(JvmLibrary, MavenPomArtifact)
.execute()
for (component in result.resolvedComponents) {
component.getArtifacts(MavenPomArtifact).each { println it.file }
}
I'm not sure if the actual artifact will be resolved with this method, too, but you may just use the path of the POM file. Please note, that you should call this functionality during the execution phase, either by defining a new task type with a #TaskAction or by using a doFirst/doLast closure.

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.

How can I get gradle to populate jars with dependency metadata?

So if I build a jar in Maven, say for example jackson-core-2.5.1.jar, I find the following in the artifact:
META-INF/maven/
META-INF/maven/com.fasterxml.jackson.core/
META-INF/maven/com.fasterxml.jackson.core/jackson-core/
META-INF/maven/com.fasterxml.jackson.core/jackson-core/pom.properties
META-INF/maven/com.fasterxml.jackson.core/jackson-core/pom.xml
Gradle, however, does not seem to create this data. Problem is that we have several components of our build, including a parent project, that aren't hosted in the same SCM location. For our large and complex build, how would Gradle know that a locally built artifact in one SCM location depends on a locally built artifact in another, if there's no metadata? What is the Gradle way to manage this situation?
Repositories contain a separate copy of pom.xml. It usually lives next to the JAR file in the physical structure on the disk. This applies to binary repositories like Nexus or Artifatory and also to your local Maven repository (under $HOME/.m2/repo).
If for some reason you want to copy the behavior of Maven you can tell Gradle to do create those files. We use this customization in subprojects closure that configures our multi-project Gradle build.
jar {
// until we have better solution
// https://discuss.gradle.org/t/jar-task-does-not-see-dependency-when-using-maven-publish/11091
if (project.tasks.findByName('generatePomFileForMavenJavaPublication')) {
dependsOn 'generatePomFileForMavenJavaPublication'
} else {
project.tasks.whenTaskAdded { addedTask ->
if (addedTask.name == 'generatePomFileForMavenJavaPublication') {
project.tasks.jar.dependsOn 'generatePomFileForMavenJavaPublication'
}
}
}
into("META-INF/maven/$project.group/$project.archivesBaseName") {
/*
from generatePomFileForMavenJavaPublication
*/
from new File(project.buildDir, 'publications/mavenJava')
rename ".*", "pom.xml"
}
}
It would be simpler if there wasn't a problem with generatePomFileForMavenJavaPublication task being created lazily sometimes. And you need to check how to create your properties file. I guess you can dump properties from a running Gradle process there.

How can I easily convert between the groupId form of a library and its associated path in the local repository?

I am using gradle to install an Android AAR package (although, this could conceivably work with a JAR or any other artifact). I can install the artifact with ./gradlew install. This will install it to my local maven repository, by default ~/.m2/repository.
This works fine. Now, I need to create a new task that can work with the actual files of that repository. I can get all of the information I need, but I have the groupId in the form: com.somecompany.project, and I WANT it in the form: com/somecompany/project (since this is how it is stored in the local maven repository on the file system).
I know that I can just convert the . characters to ${file.separator}, but, given that maven has to do this operation internally, is there a quick method for doing this that's part of the maven plugin? I'm hoping to be able to do something like:
def groupDirStructure = maven.convertGroupToPath(project.group)
If you want to get at the file you should resolve it as a dependency rather than go searching for it on the file system.
repositories {
mavenLocal()
}
configurations {
local
}
dependencies {
local 'com.somecompany.project:module:1.0'
}
task copyArtifacts(type: Copy) {
from configurations.local
into "some/dir"
}

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?

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