After a publish, I want to know what the url of the published artifact is (to use it in other gradle tasks for automated deployment).
Is there any way to capture this generated url?
After a publish, I want to know what the url of the published artifact is (to use it in other gradle tasks for automated deployment).
Is there any way to capture this generated url?
Sadly this information is unavailable via the gradle build system... What you can do is create a task that finalizes the publish
task
. Then have that task
query the maven repository for the most recent build. Maven will look in the maven-metadata.xml
file and return the <release>
tag value or the most recent upload if that's missing. You can get the exact download url from the response's Location
header.
Here is an example of how you would query a maven repo
$ curl -Is 'http://my.nexus.repo.com:8081/nexus/service/local/artifact/maven/redirect?r=Release&g=com.my.group.id&a=myArtifactId&v=RELEASE&p=war' | grep -Fi Location | cut -d' ' -f2
http://my.nexus.repo.com:8081/nexus/service/local/repositories/Release/content/com/my/group/id/myArtifactId/1.0.012/myArtifactId-1.0.012.war
Explaining the command
curl -Is http://<nexus-url>:<nexus-port>/nexus/service/local/artifact/maven/redirect?r=<nexus-repository>&g=<artifact-group-id>&a=<artifact-name>&v=<artifact-version>
curl
-I # only print return headers
-s # quiet output of curl's downloading progress
url params
r # nexus-repository name, tends to be Release or Snapshot
g # group id for the artifact
a # artifact id
v # artifact version or a link like RELEASE (don't use LATEST it's problematic)
## you can also supply classifier and extension if needed
c # artifact classifier
e # artifact extension
publish
task - you can see that yourself by running the task with --info
. –
Cyrenaica @Hollerweger answer is probably the least hackish, but it's wrong in couple of ways:
PublishToMavenLocal
and PublishToMavenRepository
. Extending it and printing a message saying artifact is published to Nexus is wrong, because that message is going to be printed even when publishing to the local Maven repo. The correct task class to use is PublishToMavenRepository
that publishes to the remote repo.repository
property.Putting it all together:
tasks.withType(PublishToMavenRepository) {
doFirst {
println("Publishing ${publication.groupId}:${publication.artifactId}:${publication.version} to ${repository.url}")
}
}
I found a local copy of a file called maven-metadata-remote.xml
that gets uploaded. It is under this dir: build/tmp/publishMavenPublicationToNexusRepository/
Example:
$ cat build/tmp/publishMavenPublicationToNexusRepository/com/example/my.package/0.1.0-SNAPSHOT/maven-metadata-remote.xml
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.example</groupId>
<artifactId>my.package</artifactId>
<version>0.1.0-SNAPSHOT</version>
<versioning>
<snapshot>
<timestamp>20180326.191238</timestamp>
<buildNumber>36</buildNumber>
</snapshot>
<lastUpdated>20180326191238</lastUpdated>
</versioning>
</metadata>
So I was able to ingest that file by adding something like this to the bottom of the build.gradle
file:
tasks.withType(PublishToMavenRepository) {
doLast {
def metadata_file_path = "build/tmp/publishMavenPublicationToNexusRepository/com/example/my.package/0.1.0-SNAPSHOT"
def metadata_XML = new File("${metadata_file_path}/maven-metadata-remote.xml").text
def metadata = new groovy.util.XmlSlurper().parseText(metadata_XML)
def BN = metadata.versioning.snapshot.buildNumber
def TS = metadata.versioning.snapshot.timestamp
println "INFO: uploaded version 0.1.0-${TS}-${BN}.pom to Nexus"
...
build/tmp/publishYour-name-herePublicationToRepotypeRepository/
- I wouldn't hardcode this path but get it based on publish task name instead. –
Cyrenaica build.gradle[.kts]
extensions (which the users of the pipeline might e.g. forget to add etc.) –
Cyrenaica You can extend all maven publish tasks and compute the the url again: I just needed the folder - For release artifacts you can also add the artifact at the end but I haven't found a good solution for SNAPSHOTs. The nexus base repo URL is expected to be known.
tasks.withType(AbstractPublishToMaven) {
doLast {
String urlString = nexusUrl.toString() + convertPackageNameToPath(publication.groupId) + "/" + publication.artifactId + "/" + publication.version
println "Artifact URL: " + urlString
}
}
static String convertPackageNameToPath(String packageName) {
return packageName.replace(".", "/");
}
Sadly this information is unavailable via the gradle build system... What you can do is create a task that finalizes the publish
task
. Then have that task
query the maven repository for the most recent build. Maven will look in the maven-metadata.xml
file and return the <release>
tag value or the most recent upload if that's missing. You can get the exact download url from the response's Location
header.
Here is an example of how you would query a maven repo
$ curl -Is 'http://my.nexus.repo.com:8081/nexus/service/local/artifact/maven/redirect?r=Release&g=com.my.group.id&a=myArtifactId&v=RELEASE&p=war' | grep -Fi Location | cut -d' ' -f2
http://my.nexus.repo.com:8081/nexus/service/local/repositories/Release/content/com/my/group/id/myArtifactId/1.0.012/myArtifactId-1.0.012.war
Explaining the command
curl -Is http://<nexus-url>:<nexus-port>/nexus/service/local/artifact/maven/redirect?r=<nexus-repository>&g=<artifact-group-id>&a=<artifact-name>&v=<artifact-version>
curl
-I # only print return headers
-s # quiet output of curl's downloading progress
url params
r # nexus-repository name, tends to be Release or Snapshot
g # group id for the artifact
a # artifact id
v # artifact version or a link like RELEASE (don't use LATEST it's problematic)
## you can also supply classifier and extension if needed
c # artifact classifier
e # artifact extension
publish
task - you can see that yourself by running the task with --info
. –
Cyrenaica Starting from @Abhijit Sarkar's answer, you can write universal solution for both remote and local publish direction:
tasks.withType(AbstractPublishToMaven) {
doLast {
println("Published ${publication.groupId}:${publication.artifactId}:${publication.version} to ${name.contains('Local') ? "local maven repository" : repositories.maven.url}")
}
}
Tasks publishing to local repo, contain 'Local' in its name (letter case matter), so the ternary operator defines a correct direction.
The DefaultMavenPublication
class exposes the following method:
@Override
public PublishedFile getPublishedFile(final PublishArtifact source) {
final String publishedUrl = getPublishedUrl(source);
final String publishedName = source.getFile().getName();
return new PublishedFile() {
@Override
public String getName() {
return publishedName;
}
@Override
public String getUri() {
return publishedUrl;
}
};
}
introduced in this commit. Maybe this could do the trick.
build.gradle
? –
Expiration © 2022 - 2024 — McMap. All rights reserved.
--info
onpublish
, since it's there. The key phrase is "Uploading", you basically want all the lines starting with that. The format isUploading your-artifact-0.1.0-20230711.160346-6.pom to /repository/snapshots-hosted/your/package/0.1.0-SNAPSHOT/your-artifact-0.1.0-20230711.160346-6.pom
etc. It boggles the mind why the plugin doesn't emit this by default :/ – Cyrenaica