Publishing Maven artifact to artifactory with different artifact ID - gradle

New to Maven Publishing. Our team has started using Artifactory and I'm trying to figure out how to publish to it, but using a custom artifact ID. Here's the relevant part of my build.gradle file
def applicationName = 'example-api'
def applicationVersion = '1.0.0.1'
def group = 'com.example.api'
def archiveName = "${applicationName}##${applicationVersion}"
bootWar {
archiveFileName = "${archiveName}.war"
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact(file("build/libs/${archiveName}.war"))
afterEvaluate {
artifactId archiveName
groupId group
version applicationVersion
}
}
}
}
artifactory {
contextUrl = "http://172.17.0.2:32447/artifactory"
publish {
repository {
repoKey = 'libs-release-local'
username = 'admin'
password = 'password1'
maven = true
}
defaults {
publications('mavenJava')
publishBuildInfo = true
publishArtifacts = true
publishPom = false
}
}
clientConfig.info.setBuildName(applicationName)
clientConfig.info.setBuildNumber(applicationVersion)
}
But it seems it's never keeps the same name as the WAR file that's produced in the build. This is the closest I've gotten:
Ideally, I'd like to have the artifact be called just 'example-api##1.0.0.1.war' since it will be deployed to Tomcat.
When I try to remove groupId, Artfactory seems unable to create a repo URL, and if I omit the the version, the artifact name is then example-api##1.0.0.1-unspecified.war
Any thoughts?

What you see is the expected behaviour.
Maven artifact names are strictly <artifactId>-<version>.<extension>.
So when you set the publication configuration as follows:
artifactId = example-api##1.0.0.1
version = 1.0.0.1
extension = war
It results in an artifact named example-api##1.0.0.1-1.0.0.1.war
I would strongly recommend dropping the version from the artifactId part, to be better aligned with Maven conventions.
An alternative would be to use an Ivy repository, which has more flexibility around specifying the artifact name.

Related

Gradle publishing same artifact with different classifier

This is a follow up for:
https://github.com/gradle/gradle/issues/21038
gradle publish jars with different classifiers, dependency missing
demo repo: https://gitlab.com/knyttl/kotlin-1.6.20-publishing-demo/-/tree/main
Consider a gradle project which publishes its test sources with different classifier:
configure<PublishingExtension> {
publications {
create<MavenPublication>(project.name) {
groupId = "demo"
artifactId = project.name.toLowerCase().replace(":", "-")
version = "ci"
from(components["kotlin"])
}
create<MavenPublication>(project.name + "-test") {
groupId = "demo"
artifactId = project.name.toLowerCase().replace(":", "-")
version = "ci"
artifact(testArtifact)
}
}
}
With this, I want to import the artifacts as:
implementation(project(":demo"))
testImplementation(project(":demo", "testJar"))
This works correctly until the publication as the testJar pom.xml overwrites the main one.
I was told that this is causes by the fact, that the project identification is the same:
You have two publications with the same coordinates (groupid, artifactid, version).
However what is the solution to this? I cannot change the artifactId, because then it wouldn't be imporatable as project(projectId, classifier).

Gradle how to publish a gradle-plugin to maven central

Hi I have a java project, which contains a submodule which is a gradle plugin. I want to publish this module to maven central.
I used this two plugins in my build.gradle:
plugins {
id 'java-gradle-plugin'
id 'maven-publish'
}
and my publishing block looks something like:
publishing {
publications {
javaLibrary(MavenPublication) {
from components.java
artifact sourcesJar
artifact javadocJar
artifactId = project.archivesBaseName
pom {
name = artifactId
description = "..."
url =
licenses {
license {
}
}
developers {
...
}
scm {
...
}
issueManagement {
...
}
ciManagement {
...
}
}
}
}
repositories { maven { url = "some local repo" } }
}
I noticed that when I build this module, the generated pom-default.xml is what I expected, but when I run gradle publishToMavenLocal and manually checked the pom.xml file in the .m2 folder, all the metadata like name description licenses are gone!
I also noticed in the .m2 folder there are 2 artifacts that are related to this single plugin, I think it's somewhat related with https://docs.gradle.org/current/userguide/plugins.html#sec:plugin_markers but I don't fully understand the meaning. Both these 2 artifacts' pom are missing the pom metadata as I described above.
Could some gradle expert help me here: how to keep the metadata in the published pom?
You should not need to manually define a MavenPublication for your plugin submodule. The java-gradle-plugin reacts to the application of the maven-publish plugin and automatically configures/creates publications for the plugin artifacts. See this line.
You are correct for the (2) artifacts produced. One is the plugin marker (single pom.xml) and the other is the actual plugin JAR artifact.
As for POM customization, Gradle seemingly provides its own the POM irrespective of any POM customization(s) you have defined: https://github.com/gradle/gradle/issues/17022
Sorry for late answer, but you can do something like this:
afterEvaluate {
tasks.withType(GenerateMavenPom) { task ->
doFirst {
// Update POM here
def pom = task.pom
pom.name = ...
pom.url = ...
pom.description = ...
pom.scm {
...
}
}
}
}
This will catch the pom of the plugin marker artifact as well.

Publish Snapshot to oss.jfrog.org with multiple modules fails with 403

I'm trying to publish a project with multiple modules to artifactory (oss.jfrog.org). When I run artifactoryPublish I get a 403 error but I know it's not a permissions issue because it works with a single module. It only fails trying publish multiple modules.
Some modules are aars and others are jars and all include sources. I can publish them all to Bintray, but can't publish to artifactory (for snapshots).
So the question is, how do I configure a multi-module project to publish snapshots to oss.jfrog.org.
I've figured out that if I change it to publish a single module and make the artifact name the same as the last part of the group, it works, but a different name doesn't work (gives 403 error).
So if group is com.example.foo I can publish foo.jar (com/example/foo/foo/1.0.0-SNAPSHOT/foo-1.0.0.jar). But I can't publish bar.jar (com/example/foo/bar/1.0.0-SNAPSHOT/bar.jar).
This gradle is included in every project's build.gradle
afterEvaluate {
publishing {
publications {
mavenPublication(MavenPublication) {
artifact sourcesJar
if (project.plugins.hasPlugin("com.android.library")) {
artifact("$buildDir/outputs/aar/${project.name}-debug.aar")
} else {
artifact("$buildDir/libs/${project.name}-${version}.jar")
}
groupId "com.example.foo"
artifactId project.name // changing this to "foo" works for a single project
version version
pom {
name.set(project.name)
url.set(POM_URL)
packaging POM_PACKAGING
version version
licenses {
license {
name.set(POM_LICENSE_NAME)
url.set(POM_LICENSE_URL)
}
}
developers {
developer {
name.set(POM_DEVELOPER)
}
}
scm {
url.set(POM_SCM_URL)
connection.set(POM_SCM_CONNECTION)
developerConnection.set(POM_SCM_DEV_CONNECTION)
}
}
}
}
}
bintray {
user = project.findProperty('bintrayUser') ?: System.getenv('BINTRAY_USER')
key = project.findProperty('bintrayApiKey') ?: System.getenv('BINTRAY_API_KEY')
configurations = ['archives']
publish = true
dryRun = true
pkg {
name = project.name
repo = BINTRAY_REPO
userOrg = BINTRAY_ORG
licenses = [POM_LICENSE_NAME]
vcsUrl = POM_SCM_URL
version {
name = project.name
released = new Date()
}
}
}
artifactory {
contextUrl = 'http://oss.jfrog.org'
publish {
repository {
repoKey = 'oss-snapshot-local'
username = project.findProperty('bintrayUser') ?: System.getenv('BINTRAY_USER')
password = project.findProperty('bintrayApiKey') ?: System.getenv('BINTRAY_API_KEY')
}
defaults {
publications('mavenPublication')
publishArtifacts = true
publishPom = true
}
}
resolve {
repoKey = 'jcenter'
}
}
}
Artifactory returns a 403 whenever you're trying to publish an artefact that already exists. In your case, if you've previously published snapshot artefacts from your multi module build, whenever you will try doing that again, you will get a 403. I know you can configure the user access to provide delete permissions to the account you are using to deploy, as indicated here. However, overwriting history is not considered a good practice.
Regarding renaming your groups and artefacts, I don't think that will provide a solution, as it's not your GAV coordinates that are the issue, but rather the fact that artefacts with matching GAV already exist.
If I may ask, why do you want to use SNAPSHOT artefacts? Can you not achieve the same behaviour with dynamic dependencies and dependency locking?

Confused about process to publish snapshots to BinTray

I want to investigate publishing Hibernate ORM jars to Bintray. However one requirement we have is to be able to publish snapshots, which I see Bintray now supports through this OJO repository. However, I am quite confused about how this is supposed to work after reading the documentation.
First, the documentation mentions that I should be able to request publishing to JCenter and at the same time be able to request to be able to publish snapshots. However, I see no such options: https://bintray.com/hibernate/artifacts/hibernate-orm
Secondly, after I get the account on OJO set up, what, if anything, do I need to do special with the Bintray/Gradle plugin?
After many trial and errors I've ended up with the following setup.
We use 2 different plugins for publishing:
snapshots and release publishing (using com.jfrog.artifactory) and
bintray-related activities (using com.jfrog.bintray) in gradle (in the project p6spy).
Relevant parts from the build.gradle file follow, please note the specifics of the project :
plugins {
...
// to publish !SNAPSHOTs to bintray and sync it to maven-central
// ./gradlew bintrayUpload
id 'com.jfrog.bintray' version '1.7.3'
// to publish SNAPSHOTs and !SNAPSHOTs to oss.jfrog.org
// ./gradlew artifactoryPublish
id 'com.jfrog.artifactory' version '4.5.2'
}
publishing {
publications {
maven(MavenPublication) {
from components.java
groupId project.group
artifactId project.archivesBaseName
version project.version
...
pom {
packaging 'jar'
withXml {
asNode().children().last() + {
def builder = delegate
// maven central publishing mandatories
builder.name project.name
builder.description description
builder.url 'https://github.com/p6spy/p6spy'
builder.licenses {
builder.license {
builder.name 'The Apache Software License, Version 2.0'
builder.url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
builder.distribution 'repo'
}
}
builder.scm {
builder.url 'http://github.com/p6spy/p6spy'
builder.connection 'scm:git:git://github.com/p6spy/p6spy.git'
builder.developerConnection 'scm:git:ssh://github.com:p6spy/p6spy.git'
}
builder.developers {
builder.developer {
builder.name 'Quinton McCombs'
builder.email 'quinton.mccombs#gmail.com'
}
builder.developer {
builder.name 'Peter Butkovic'
builder.email 'butkovic#gmail.com'
}
builder.developer {
builder.name 'Felix Barnsteiner'
builder.email 'felix.barnsteiner#isys-software.de'
}
}
// maven central publishing optionals
builder.issueManagement {
builder.system 'github'
builder.url 'https://github.com/p6spy/p6spy/issues'
}
builder.ciManagement {
builder.system 'Travis CI'
builder.url 'https://travis-ci.org/p6spy/p6spy'
}
}
}
}
}
}
}
// to publish SNAPSHOTs to http://oss.jfrog.org/oss-snapshot-local/
// and !SNAPSHOTs to http://oss.jfrog.org/oss-release-local/
artifactory {
contextUrl = 'https://oss.jfrog.org'
resolve {
repository {
repoKey = 'libs-release'
}
}
publish {
repository {
// The Artifactory repository key to publish to
// when using oss.jfrog.org the credentials are from Bintray.
if (project.version.endsWith("-SNAPSHOT")) {
repoKey = 'oss-snapshot-local'
} else {
repoKey = 'oss-release-local'
}
username = System.getenv('BINTRAY_USER')
password = System.getenv('BINTRAY_API_KEY')
}
defaults {
publications 'maven'
properties = [ 'bintray.repo': 'p6spy/maven', 'bintray.package': 'p6spy:p6spy', 'bintray.version': project.version.toString() ]
}
}
}
// to publish to bintray and later sync to maven-central
bintray {
user = System.getenv('BINTRAY_USER')
key = System.getenv('BINTRAY_API_KEY')
publications = ['maven']
// dryRun = true
// publish = true
pkg {
repo = 'maven'
name = 'p6spy:p6spy'
userOrg = group
desc = description
websiteUrl = 'https://github.com/p6spy/p6spy'
issueTrackerUrl = 'https://github.com/p6spy/p6spy/issues'
vcsUrl = 'https://github.com/p6spy/p6spy.git'
licenses = ['Apache-2.0']
publicDownloadNumbers = true
githubRepo = 'p6spy/p6spy'
githubReleaseNotesFile = 'docs/releasenotes.md'
version {
released = new Date()
name = project.version
vcsTag = "p6spy-${project.version}"
// Optional configuration for Maven Central sync of the version
mavenCentralSync {
sync = true //[Default: true] Determines whether to sync the version to Maven Central.
close = '1' //Optional property. By default the staging repository is closed and artifacts are released to Maven Central. You can optionally turn this behaviour off (by puting 0 as value) and release the version manually.
user = System.getenv('SONATYPE_USERNAME') //OSS user token: mandatory
password = System.getenv('SONATYPE_PASSWORD') //OSS user password: mandatory
}
}
}
}
UPDATE
Published:
snapshots are in: http://oss.jfrog.org/oss-snapshot-local/p6spy/p6spy/ (I just followed official docs: https://www.jfrog.com/confluence/display/RTF/Deploying+Snapshots+to+oss.jfrog.org)
releases end up in: http://oss.jfrog.org/oss-release-local/p6spy/p6spy/ and are later auto-synced to maven central: http://repo1.maven.org/maven2/p6spy/p6spy/

Publish wrapped OSGi bundles to artifactory with Gradle

As not all jars are automatically usable OSGi bundles I use wrapping to generate them. After having being wrapped I'd like to publish them to my Artifactory repository. However, my lack of understanding of Gradle inhibits success, and after reading several suggested Stackoverflow answers I am still stuck.
This is my build.gradle file:
buildscript {
repositories {
maven { url 'http://localhost:8081/artifactory/gradle-dev' }
}
dependencies {
classpath 'org.standardout:bnd-platform:1.2.0'
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
}
}
apply plugin: 'org.standardout.bnd-platform'
apply plugin: "com.jfrog.artifactory"
apply plugin: 'maven-publish'
group = 'com.google.code.gson'
version = '2.8.0'
publishing {
publications {
osgiBundles(MavenPublication) {
artifacts {
files("build/plugins")
}
}
}
}
artifactory {
contextUrl = "${artifactory_contextUrl}" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'gradle-dev-local'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
defaults {
publications ('osgiBundles')
}
}
resolve {
repository {
repoKey = 'gradle-dev'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
}
}
platform {
useBndHashQualifiers = false
defaultQualifier = ''
bundle(group: 'com.google.code.gson', name:'gson', version:'2.8.0') {
bnd {
instruction 'Export-Package', 'com.google.gson,com.google.gson.stream,com.google.gson.annotations,com.google.gson.reflect'
}
}
}
The output of the script is as follows:
gradle artifactoryPublish
:generatePomFileForOsgiBundlesPublication
:artifactoryPublish
Deploying artifact: http://localhost:8081/artifactory/gradle-dev-local/com/google/code/gson/bundle-jars/2.8.0/bundle-jars-2.8.0.pom
Deploying build descriptor to: http://localhost:8081/artifactory/api/build
Build successfully deployed. Browse it in Artifactory under http://localhost:8081/artifactory/webapp/builds/bundle-jars/1489323863518
When I look in the artifactory repository the structure is not what I expected:
+- com
+--- google/code/gson/bundle-jars
|+-- 2.8.0
| +- bundle-jars.pom
+--- maven-metadata.xml
The wrong directory structure (google/code/gson/bundle-jars), where I expected several sub directorties (google, code, gson) with a 2.8.0 and a jar file.
I think I have to change the publications block, but I don't know what it should be.
I use unpuzzle (or rather this fork) to create Maven artifacts from OSGi bundles (and publish them to Artifactory).
This is probably not the most efficient solution for your use case, but at least something that works and I can come up with fast.
Here is an example of where I use unpuzzle for this purpose. Maybe that can serve as a starting point (together with the unpuzzle docs). There is a lot of bloat in my example because there I try to actually determine the original Maven artifacts for OSGi bundles created from them - as you always want the OSGi bundle, that's probably not relevant for you.
Note that by default the published artifacts will have different names (based on the bundle symbolic name) and a different group (which is configurable). But I think that is to be preferred over having the original group and name, otherwise it may get confused w/ the original. Adapting the group and name individually is possible as you can see in the example.
The publication should be as follows:
publishing {
publications {
osgiBundles(MavenPublication) {
groupId 'my.group'
artifactId 'com.google.code.gson'
version '2.8.0'
artifact file("build/plugins/com.google.code.gson_2.8.0.jar")
}
}
}

Resources