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).
Related
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.
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.
I have a library containing usual classes and those especially for unit tests. So I want to publish two separate artifacts from the same project. My working solution with the maven plugin looks like this:
task jarTest (type: Jar, dependsOn: testClasses) {
from sourceSets.test.output
archiveBaseName.set('foo-test')
description = 'test utilities'
}
artifacts {
archives jarTest
}
uploadArchives {
repositories {
mavenDeployer {
//...
addFilter('foo') {artifact, file ->
artifact.name == 'foo'
}
addFilter('foo-test') {artifact, file ->
artifact.name == 'foo-test'
}
}
}
}
Unfortunately the maven plugin is deprecated and will be removed in Gradle 7. maven-publish is the suggested replacement and I'm looking for a replacement solution.
My current attempt looks like
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
artifact jarTest
}
}
}
There is the obvious problem that there are two artifacts with the same name.
Setting the name like this does not work:
artifactId = jar.archiveBaseName
this neither:
afterEvaluate {
artifactId = jar.archiveBaseName
}
It's possible to configure the artifact like this
artifact(jar) {
classifier "src"
extension "zip"
}
But there is no property for the name regarding the documentation (https://docs.gradle.org/current/dsl/org.gradle.api.publish.maven.MavenArtifact.html).
So I'm looking for sth. like the addFilter from the maven plugin.
How can I create fat jar for gradle plugin, publish it and then use it in another project ?
I have tried:
publishing {
publications {
shadow(MavenPublication) {
groupId = 'group'
artifactId = 'plugin'
version = '1.0-SNAPSHOT'
from components.shadow
}
}
}
But I am failing with applying it in another project.
Can someone show me the working example ?
Thank you for any help.
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")
}
}
}