publishing to bintray & oss.jfrog.org with gradle & maven-publish

publishing to bintray & oss.jfrog.org without bintray plugin & artifactory plugin

introduction

One possibility to publish jvm based open source project is bintray with a combination of the maven-publish, bintray plugin and artifactory plugin:

  • maven-publish (gradle standard plugin) to define the pom details and what should be published,

  • the bintray plugin to upload and publish a package to a bintray repository and jcenter,

  • and the artifactory plugin to publish snapshot releases to the snapshot artifactory repository.

Three plugins? Isn’t that something that maven-publish can do alone? Maybe, but to get all this running I just followed the docs.

I have a short article about bintray with a couple of links that helped me with the setup.

the issue

Finally, it was running, and there was more interesting stuff to spend time on than publishing. ;-)

When I updated the builds (multiple jars) of my project to the latest gradle version (6.5) I hit an issue with publishing.

Starting with gradle 6, gradle publishes additional metadata for a package. Unfortunately the bintray gradle plugin doesn’t currently support this.

It is possible to disable the additional gradle metadata but there is a better solution that doesn’t need the bintray plugin. With the bintray plugin gone, the second goal is to remove the artifactory plugin too and just use maven-publish.

replacing the bintray plugin

The mentioned bintray issue shows a workaround with some code that "patches" the bintray publishing. I’m trying to avoid "funny" code in the build.gradle because it reduces readability. Especially for other people that do not know what it is supposed to do (or for me after a few weeks…​).

Another comment suggests using the maven-publish plugin.

That is interesting because that was a thought right from the beginning. It looks very simple, it fixes the issue, and it reduces the number of plugins required for publishing. Too good to be true!

All there is to do is configuring a maven repository for publishing with a special bintray url:

publishing {
    publications {
         same as with bintray plugin
    }

    repositories {
        maven {
          name = "bintray"
          url = uri("https://api.bintray.com/maven/openapi-processor/primary/${project.name}/;publish=1;override=0")
          credentials {
            username = bintrayUser
            password = bintrayKey
          }
        }
    }
}

The description of the api uses three placeholders

/maven/:subject/:repo/:package/:file_path[;publish=0/1][;override=0/1]
  • :subject, the user or organization

  • :repo, the repository name

  • :package, the package name, i.e. the artifact id.

  • :file_path, the file path in the repository, this is automatically added by the maven-publish plugin.

  • publish & override matrix parameters, they control if the artifacts should be published (false/true) and if it can be overridden (false/true).

Running the publish<Publication>To<RepositoryName>Repository task with --info will log the full url, e.g.

https://api.bintray.com/maven/openapi-processor/primary/openapi-processor-spring/;publish=1;override=0/io/openapiprocessor/openapi-processor-spring/1.0.0.M15x/openapi-processor-spring-1.0.0.M15.jar'

The publish…​ task appends the :file_path at the end of the url. That looks a bit strange with the matrix parameters in the middle. That’s ok though, because the matrix parameters don’t have to be at the end (like query parameters).

Of course there is another issue. Gradle does not only add gradle specific metadata but also additional .sha256 and .sha512 checksum files. Those extra files seem to confuse bintray, and the checksum files end up in an additional wrong folder.

Luckily this is easy to fix by disabling the new checksum files (for now) with the following property in gradle.properties:

systemProp.org.gradle.internal.publish.checksums.insecure=true

First goal reached. It fixes the metadata issue, and the bintray plugin is no longer required.

replacing the artifactory plugin

If maven-publish works for bintray it should work for artifactory too. It does, it just needs a different repository url.

publishing {
    publications {
        // same as with bintray/artifactory plugin
    }

    maven {
      name = "bintray-snapshots"
      url = uri("https://oss.jfrog.org/oss-snapshot-local/")
      credentials {
        username = bintrayUser
        password = bintrayKey
      }
    }
}

Second goal reached. The artifactory plugin is no longer required.

automatically switching repository

What is left todo is automatic selection of the correct repository. Snapshots should use the "bintray-snapshots" repository and normal releases should use the "bintray" repository.

The gradle documentation shows the following solution:

publishing {
    repositories {
        maven {
            def releaseRepository = uri("https://api.bintray.com/maven/openapi-processor/primary/${project.name}/;publish=1;override=0")
            def snapshotRepository = uri("https://oss.jfrog.org/oss-snapshot-local/")
            url = version.endsWith('SNAPSHOT') ? snapshotRepository : releaseRepository
        }
    }
}

Simple enough and easy to understand. :-)

conclusion

There are probably limitations regarding specific bintray and artifactory features that are not available using maven-publish, but it looks like that it is not an issue for simple publishing.

The advantages are:

  • just one plugin instead of three plugins for publishing

  • simpler configuration with less duplication

That’s it.