Best approach for declaring BinTray JCenter repository


(David M. Carr) #1

JFrog’s [BinTray] (https://bintray.com/) appears to be an attempt at providing a social approach to distribution of open source binaries. In many ways, their Java-oriented JCenter repository can be viewed as an alternative to Maven Central. I would like for there to be an easy way to declare in a Gradle build that I would like to use JCenter as a repository. What are the preferred ways to do so, both with existing released versions of Gradle, and in the future?

Ideally, I’d like it to be a standard part of the DSL. For example, something like this could work:

repositories {

bintrayJCenter()

}

I’ve taken a quick pass at adding support for that to Gradle core, and gotten it working here.

I think that this approach would be what most people want and expect. One main “gotchas” I see are that it requires adding a new method to the RepositoryHandler interface (oh, if only we had defender methods). Another is the possibility of change to the JCenter itself (its URL, availability, etc.), which I don’t know how to judge, given that I’m not part of JFrog, and it’s still a beta service.

JFrog’s tweet indicates they may be working on something along these lines.

In terms of other approaches applicable right now, I know that you can declare JCenter as a mavenRepo with the URL, like this:

repositories {

mavenRepo(url: ‘http://jcenter.bintray.com’)

}

You could use an init script to add this automatically to a build (as part of a custom Gradle distribution pulled down by the Gradle wrapper if desired).

Another approach would be to extract logic relating to BinTray into a plugin. The simplest such plugin would just add a repository definition automatically upon application. A more complex plugin might add a “bintray” extension; something like this:

bintray {

jcenterRepo()

repo(userName: ‘davidmc24’, repoName: ‘myRepo’)

}

This approach could easily handle both JCenter as well as other repositories. However, you run into a bit of a bootstrapping problem, in that you then would need to acquire the plugin from somewhere other than BinTray. The path of least resistance would seem to be to publish the plugin to Maven Central.

So, all that being said… are there other approaches that I should consider? Which approaches are recommended?


(Luke Daley) #2

Hi David,

I would consider adding a plugin that adds an extension to the ‘repositories’ handler. The JavaScript plugin is a good example of this:

https://github.com/gradle/gradle/blob/master/subprojects/javascript/src/main/groovy/org/gradle/plugins/javascript/base/JavaScriptBasePlugin.groovy#L29

Then you’d have something like:

repositories {
  bintray.jcenter()
}

As for the bootstrapping problem, that’s tricky. The path of least resistance right now would be to publish the Gradle plugin in Maven Central. We are working to improve this situation.


(David M. Carr) #3

Thanks for the suggestion, Luke. While I hope that at some point in the future there will be a more elegant solution to the bootstrapping problem, this is a good approach for right now. I’ll pursue a plugin in that direction (and likely publish it in Maven Central).

Where is the appropriate place to publish announcements of new plugins?


(Peter Niederwieser) #4

This forum is a good place to announce your plugin(s).


(David M. Carr) #5

I’ve made some progress towards the suggested plugin. I’ve gotten a RepositoryHandler extension working based on the provided example. I had been developing my plugin as a standalone plugin, but when I went to test it, I realized that (as far as I know) there isn’t any way to declare the use of a standalone plugin such that it will be available for use within the buildscript block. That would mean that the “bintray” extension would only be available for project.repositories, not project.buildscript.repositories.

I think I’ve found an alternate approach that bypasses both this restriction and the need to publish the plugin to Maven Central. From my initial testing, it seems that an external build script loaded using “apply from:” within the buildscript block can register extension handlers on both the project and buildscript RepositoryHandlers such that the extensions are then available for the remainder of the build script. Are there any downsides or other gotchas I should know about with this technique?


(David M. Carr) #6

I’m happy with how the external build script approach turned out.

To load the plugin:

buildscript {
    apply from: 'https://bitbucket.org/davidmc24/gradle-bintray-plugin/raw/0.1.0/Bintray.gradle'
}

Example repository definitions using the plugin:

repositories {
    bintray.jcenter() // Bintray-owned, allows anonymous access
    bintray.repo(repoOwner: 'davidmc24', repoName: 'gradle-plugins') // Uses credentials from gradle.properties
    bintray.repo(repoOwner: 'WowCorp', repoName: 'AmazingSoftware') {
        credentials {
            username = 'joe'
            password = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
        }
    }
}

https://bitbucket.org/davidmc24/gradle-bintray-plugin


(Peter Niederwieser) #7

Thanks for developing a plugin for Bintray. Two things to be aware of when using the “external build script” approach:

  • To my knowledge, applying plugins in the ‘buildscript’ block isn’t an official feature. * Remote script plugins aren’t currently cached. Hence you’ll have to be online to build, even if all dependencies are cached.

(David M. Carr) #8

Thanks for the reply.

  • I didn’t think that applying external build scripts in the ‘buildscript’ block was an official feature (otherwise I would have expected it to be mentioned explicitly somewhere in the documentation). I’ve called out in the documentation for the plugin that it uses internal APIs that are subject to change, as well as which versions of Gradle the plugin has been tested against. If this technique stops working, and a similar replacement isn’t found, then that would likely be the end of the plugin in its current form (which would be fine; there are other reasonable alternatives).

  • That being said, I’m not the first one to use it. I came across the idea in this gradle-user post.

  • If I’m lucky, if this technique breaks, by then some form of Bintray support will already have been added to Gradle core. :slight_smile: * I was aware that remote script plugins aren’t currently cached. However, I’ll add the “must be online to build” caveat to my plugin’s documentation, since that may be a showstopper for some people.

  • If I’m understanding correctly, “remote script plugins” means “any script loaded via a URL”? If that’s the case, then perhaps downloading a copy of ‘Bintray.gradle’ and referencing it with a project-relative path would be an adequate workaround?