Publish wrapped OSGi bundles to artifactory with Gradle - 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")
}
}
}

Related

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?

Publishing Maven artifact to artifactory with different artifact ID

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.

Move publishing configuration to one place in gradle

I have a project which has modules, my goal is to configure publishing after each module is built and after all modules are built, so I could create a zip file with all the jars inside and upload it as well. I do it in subprojects section and in outer section.
publishing {
publications {
mavenJava(MavenPublication) {
//my artifacts here
}
}
repositories {
maven {
url "${artifactoryURL}"
credentials {
username = "${artifactoryUsername}"
password = "${artifactoryPassword}"
}
}
}
}
Is there a way to move repositories configuration to one place, so I could avoid duplication of this configuration?
I guess that you're creating your deployables in a top-level (root, parent) project, that does not have any sources.
Is there a way to move repositories configuration to one place, so I could avoid duplication of this configuration?
Sure. Just use subprojects, allprojects or generic configure, depending on your needs:
allprojects {
id 'maven-publish'
publishing {
repositories {
maven {
url "http://maven.repo"
}
}
}
}
This will configure publishing for all the projects (be aware of that you may not want to publish everything).
For a projects with Java source you can configure publishing like usual:
subprojects {
publishing {
publications {
main(MavenPublication) {
from components.java
artifact sourcesJar
artifact javadocJar
}
}
}
}
And for root project just configure deployments as in your previous question.

Artifact is not published using gradle and artifactory plugin

I'm trying to upload a simple zip to artifactory using gradle. This is my script:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:latest.release"
}
}
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
def user = "$System.env.ARTIFACTORY_USER"
def pass = "$System.env.ARTIFACTORY_PASSWORD"
task createArchive(type: Zip){
baseName 'myzip'
destinationDir(new File('target'))
from '.'
exclude 'target'
exclude '.gradle'
exclude 'build.gradle'
exclude 'README.md'
doFirst{
new File('target').mkdirs()
}
}
task clean(type: Delete){
delete 'target'
}
publishing {
publications {
customArtifact(MavenPublication) {
artifact createArchive
}
}
}
artifactory {
publish {
contextUrl = 'http://myrepo/artifactory'
repository {
repoKey = "myrepo-tools"
username = user
password = pass
}
publications ('customArtifact')
}
}
The code seems to work fine but actually only the build info are published. The zip is not:
Deploying build descriptor to: http://myrepo/artifactory/api/build
Build successfully deployed. Browse it in Artifactory under http://myrepo/artifactory/webapp/builds/myproject/1503338121156
My code does not seem different from the one published here: How to build Groovy JAR w/ Gradle and publish it to in-house repo (which was pointed as reference in question nothing published to artifactory using gradle artifactory plugin) but I'm not sure that is still valid since is quite old.
The main difference is that almost all the examples are using java plugin so they have the from components.java line in the publications. In my case I cannot use it as I have a custom zip.. but I can't find what else can be changed.
Thanks,
Michele.

Resources