# Plugin Portal & Improving Plugin Development

**URL:** <https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568>\
**Category:** Old Forum Archive\
**Created:** [September 29, 2011, 4:18pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568 "2011-09-29T16:18:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![hansd](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/hansd/32/3_2.png) [@hansd](https://discuss.gradle.org/u/hansd)\
**Post date:** [September 29, 2011, 4:18pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/1 "2011-09-29T16:18:00Z")

</div>

summary: Making it easier to retrieve, publish, host, test and document plugins and providing an online service for hosting Gradle open source plugins. status: Discussions are happening and work will start not long after the release of 1.0 code: planned

The plugin portal will enable Gradle users to more conveniently reuse plugins and scripts developed by other Gradle users. The portal will act as a database, with an interface to search for and find out about the plugins that are out there. Other planned features:

- Hosts multiple versions of the same plugin \* Runs nightly automated tests to validate which versions of a plugin works with which version of Gradle (including the latest Gradle from trunk). \* Provides a staging workflow for publishing new plugins (Do they provide documentation, integration tests, …) \* Gradle would also provide a Plugin Development plugin that makes it very easy to write and publish plugins. \* The source and the actual binaries of the plugins can live wherever the author wants them to live.

This will include a set of Gradle plugins that make it easier to retrieve, publish, host, test and document plugins. This won’t depend on the host which might be the official Gradle open source plugin portal but can also be any internal enterprise repository manager.

---

<div class="post-metadata">

**Author:** ![curious\_attempt\_bunn](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/curious_attempt_bunn/32/120_2.png) [@curious\_attempt\_bunn](https://discuss.gradle.org/u/curious_attempt_bunn)\
**Post date:** [September 29, 2011, 7:59pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/2 "2011-09-29T19:59:00Z")

</div>

This is at the top of my personal wish list for Gradle. These are my primary pain points: “…retrieve, publish, host …”.

I’m keen to work on these issues and contribute improvements. Finding the best way to fit into the roadmap and agree on the correct direction for Gradle have been the main blockers to date.

GRADLE-1677 was a step towards the _retrieve_ portion, as was GRADLE-1653. These two mailing list discussion threads relate to GRADLE-1677:

[http://gradle.1045684.n5.nabble.com/easy-plugin-integration-td4542479.html](http://gradle.1045684.n5.nabble.com/easy-plugin-integration-td4542479.html)[http://gradle.1045684.n5.nabble.com/Ideas-for-simplifying-the-bootstrapping-of-plugin-loading-td4588130.html](http://gradle.1045684.n5.nabble.com/Ideas-for-simplifying-the-bootstrapping-of-plugin-loading-td4588130.html)

---

<div class="post-metadata">

**Author:** ![curious\_attempt\_bunn](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/curious_attempt_bunn/32/120_2.png) [@curious\_attempt\_bunn](https://discuss.gradle.org/u/curious_attempt_bunn)\
**Post date:** [September 30, 2011, 7:00pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/3 "2011-09-30T19:00:00Z")

</div>

I’d like to revive the discussion around the retrieval part of this roadmap item. Is this forum topic a good place for it?

---

<div class="post-metadata">

**Author:** ![adammurdoch](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/adammurdoch/32/17_2.png) [@adammurdoch](https://discuss.gradle.org/u/adammurdoch)\
**Post date:** [September 30, 2011, 7:47pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/4 "2011-09-30T19:47:00Z")

</div>

yes it is

---

<div class="post-metadata">

**Author:** ![curious\_attempt\_bunn](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/curious_attempt_bunn/32/120_2.png) [@curious\_attempt\_bunn](https://discuss.gradle.org/u/curious_attempt_bunn)\
**Post date:** [September 30, 2011, 8:20pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/5 "2011-09-30T20:20:00Z")

</div>

@adam Great!

Here’s my recap of this thread [http://gradle.1045684.n5.nabble.com/easy-plugin-integration-td4542479.html](http://gradle.1045684.n5.nabble.com/easy-plugin-integration-td4542479.html)

In terms of the user experience, we settled on this:

> "Being able to inline the dependency declaration into the apply statement is something we've discussed before. The plan is to have the apply statement handle dependency coordinates. You would be able to do any of the following:
> 1. apply group: ‘mygroup’, name: ‘myplugin-project’, version: ‘1.0’, plugin: ‘myplugin’ 2. apply group: ‘mygroup’, plugin: ‘myplugin’, version: ‘1.0’
> 
> 2. apply plugin: ‘myplugin’"

We then came up with a technical solution:

> "I think there are really 2 options to solving this: 1. Limit the places where this type of apply statement can appear in the script, eg it must be a top-level statement. 2. Don't even try to support changing the build script classpath.
> 
> I’d go with option 2. The apply method would work something like this: 1. create a new configuration containing the plugin dependency, and resolve the configuration. 2. create a URLClassLoader from the resulting files. The parent ClassLoader should be GradleInternal.getScriptClassLoader().
> 
> 1. use the ClassLoader to look up the plugin.
> 
> Nice and simple. It might be good to have a cache of classloaders created in step 2, so we can share the implementation classes across all projects in a build (and, when using the daemon, across builds).
> 
> What is interesting about this approach is that plugins are isolated from each other. The big downside is that the plugin cannot contribute classes to the build script. But I think it might be a good thing to move away from needing to do this."

During the discussion of related issues to the technical solution we stalled here:

> "The more I consider this, the more it just feels wrong (by “this” I mean not exposing types from plugins to the build file compile). I can see it being a source of much confusion and annoyance to users. Not having types as first class citizens has an unclean feel to it and seems like a compromise which has the potential to turn people off. I think we need to keep searching for a cleaner solution."

What would help us proceed?

---

<div class="post-metadata">

**Author:** ![curious\_attempt\_bunn](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/curious_attempt_bunn/32/120_2.png) [@curious\_attempt\_bunn](https://discuss.gradle.org/u/curious_attempt_bunn)\
**Post date:** [September 30, 2011, 8:26pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/6 "2011-09-30T20:26:00Z")

</div>

Something that caught my eye from the other thread was the wish to be able to do something akin to this also:

```gradle
apply plugin: 'company-plugin', fromJar: 'url://to/company-plugin.jar'

```

See: [http://gradle.1045684.n5.nabble.com/Ideas-for-simplifying-the-bootstrapping-of-plugin-loading-td4588130.html](http://gradle.1045684.n5.nabble.com/Ideas-for-simplifying-the-bootstrapping-of-plugin-loading-td4588130.html)

Although for my taste anything we do needs to be compatible with working without a network connection.

---

<div class="post-metadata">

**Author:** ![elberry](https://avatars.discourse-cdn.com/v4/letter/e/e9c0ed/32.png) [@elberry](https://discuss.gradle.org/u/elberry)\
**Post date:** [October 4, 2011, 9:54pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/7 "2011-10-04T21:54:00Z")

</div>

I had suggested that, but I think I can live with using apply from.

This seems to work for me:

Remote Script:

```gradle
buildscript {
   repositories {
      mavenRepo urls: ['http://internal.company.com/artifactory/repo']
   }
   dependencies {
      classpath 'com.company:company-plugin:11.4'
   }
}
  apply plugin: 'company-plugin'

```

Local Script (Single Project):

```gradle
apply from: 'file:///Users/elberry/development/projects/mine/test/remote.gradle'

```

Local Script (Multiple Project):

```gradle
subprojects {
   apply from: 'file:///Users/elberry/development/projects/mine/test/remote.gradle'
}

```

This seems to solve my issues, and seems to work fine on 1.0M3. I think there were some drawbacks to this though, and I haven’t tested it with 1.0M5 yet.

---

<div class="post-metadata">

**Author:** ![elberry](https://avatars.discourse-cdn.com/v4/letter/e/e9c0ed/32.png) [@elberry](https://discuss.gradle.org/u/elberry)\
**Post date:** [October 25, 2011, 7:34pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/8 "2011-10-25T19:34:00Z")

</div>

This no longer seems to work for me in milestone-5.

There is an existing bug for this however: GRADLE-1517

---

<div class="post-metadata">

**Author:** ![Damokles](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/damokles/32/9342_2.png) [@Damokles](https://discuss.gradle.org/u/Damokles)\
**Post date:** [November 3, 2011, 9:32am UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/9 "2011-11-03T09:32:00Z")

</div>

Wouldn’t it be best if there was a central repository hosted by gradle where all the plugins could live. This would make using them much easier in the long run since we would not have to track the location of each plugin, but can simply rely on the central repository.

---

<div class="post-metadata">

**Author:** ![adammurdoch](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/adammurdoch/32/17_2.png) [@adammurdoch](https://discuss.gradle.org/u/adammurdoch)\
**Post date:** [November 4, 2011, 12:05am UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/10 "2011-11-04T00:05:00Z")

</div>

This is exactly the idea of the plugin portal. It’s a central repository that you point your build at to find plugins.

This repository may or may not actually host the plugins. It may instead simply point Gradle at the real location of the plugin. Either way, the build author does not need to know where the plugin happens to live, Gradle + the plugin portal will take care of this.

At this stage, I think the preference is that the portal will physically host the plugins.

---

<div class="post-metadata">

**Author:** ![Damokles](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/damokles/32/9342_2.png) [@Damokles](https://discuss.gradle.org/u/Damokles)\
**Post date:** [November 4, 2011, 10:59am UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/11 "2011-11-04T10:59:00Z")

</div>

We use artifactory to proxy external repositories to protect us against outages and to increase speed for the team. If the plugins where not in a central maven compatible repository but spread out over the net we could not proxy them with artifactory.

---

<div class="post-metadata">

**Author:** ![luke\_daley](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/luke_daley/32/9890_2.png) [@luke\_daley](https://discuss.gradle.org/u/luke_daley)\
**Post date:** [November 4, 2011, 11:22am UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/12 "2011-11-04T11:22:00Z")

</div>

My intention for this is that if we do allow you to host your binaries anywhere, we will proxy it in some fashion so there is always a consistent URL scheme you can hit.

My preference at this stage is this approach, but at least initially it may be a requirement that we host the binaries.

---

<div class="post-metadata">

**Author:** ![curious\_attempt\_bunn](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/curious_attempt_bunn/32/120_2.png) [@curious\_attempt\_bunn](https://discuss.gradle.org/u/curious_attempt_bunn)\
**Post date:** [January 12, 2012, 8:49pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/13 "2012-01-12T20:49:00Z")

</div>

I’m looking to work on this again next week (GRADLE-1677) at the local Hackergarten event. Are there any high-level decisions we need to make beforehand?

Quick recap:

"Being able to inline the dependency declaration into the apply statement is something we’ve discussed before. The plan is to have the apply statement handle dependency coordinates. You would be able to do any of the following:

1. apply group: ‘mygroup’, name: ‘myplugin-project’, version: ‘1.0’, plugin: ‘myplugin’ 2. apply group: ‘mygroup’, plugin: ‘myplugin’, version: ‘1.0’

2. apply plugin: ‘myplugin’ "

---

<div class="post-metadata">

**Author:** ![Peter\_Niederwieser](https://avatars.discourse-cdn.com/v4/letter/p/9f8e36/32.png) [@Peter\_Niederwieser](https://discuss.gradle.org/u/Peter_Niederwieser)\
**Post date:** [January 12, 2012, 10:36pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/14 "2012-01-12T22:36:00Z")

</div>

It would be nice to have a short notation, e.g. _apply plugin: “mygroup:myplugin-project:1.0:myplugin”_ or _apply plugin: “myplugin”, from: “mygroup:myplugin-project:1.0”_

---

<div class="post-metadata">

**Author:** ![elberry](https://avatars.discourse-cdn.com/v4/letter/e/e9c0ed/32.png) [@elberry](https://discuss.gradle.org/u/elberry)\
**Post date:** [January 12, 2012, 11:01pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/15 "2012-01-12T23:01:00Z")

</div>

and perhaps a shorthand for specifying repository along with it. Eg.

```gradle
apply plugin: "mygroup:myplugin-project:1.0", mvn: "http://host/repo"

```

or

```gradle
apply plugin: "mygroup:myplugin-project:1.0", ivy: "http://host/repo/[artifact]-[pattern]"

```

---

<div class="post-metadata">

**Author:** ![luke\_daley](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/luke_daley/32/9890_2.png) [@luke\_daley](https://discuss.gradle.org/u/luke_daley)\
**Post date:** [January 13, 2012, 10:59am UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/16 "2012-01-13T10:59:00Z")

</div>

@Merlyn: the build classpath needs to be constructed before any calls to apply(), so it’s not clear to me how we’d use the dependency coordinates so late in the lifecycle.

Apart from that problem, I like the notation.

---

<div class="post-metadata">

**Author:** ![curious\_attempt\_bunn](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/curious_attempt_bunn/32/120_2.png) [@curious\_attempt\_bunn](https://discuss.gradle.org/u/curious_attempt_bunn)\
**Post date:** [January 14, 2012, 2:16am UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/17 "2012-01-14T02:16:00Z")

</div>

Yes. That’s tricky. Either the apply function needs to be part of the first pass of the script (tricky/dangerous), or the dependency of the plugin is not shared (with the build script itself and the other plugins).

Last time we discussed this the sticking point was around making classes like Tasks available to the build script.

---

<div class="post-metadata">

**Author:** ![luke\_daley](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/luke_daley/32/9890_2.png) [@luke\_daley](https://discuss.gradle.org/u/luke_daley)\
**Post date:** [January 14, 2012, 4:19pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/18 "2012-01-14T16:19:00Z")

</div>

Treating these things like script plugins in that they’ll have their own isolated classloader hierarchy sounds like a good idea to start with. That should work.

---

<div class="post-metadata">

**Author:** ![adammurdoch](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/adammurdoch/32/17_2.png) [@adammurdoch](https://discuss.gradle.org/u/adammurdoch)\
**Post date:** [January 17, 2012, 9:42pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/19 "2012-01-17T21:42:00Z")

</div>

I can see 4 broad strategies here:

1. We extract all the calls to ‘apply’ in a pass that runs before we assemble the final script classpath, and use these calls to decide what to add to the script classpath. This may or may not be the same pass that evaluates the ‘buildscript { }’ blocks. 2. We use some mechanism for adding stuff to the script classpath that is separate from applying the plugin (this is the strategy we use now). 3. We get rid of the need for plugins to be visible on the script classpath. 4. Transform the build script so that unresolved static types are replaced with dynamic types, and have the ‘apply’ statements contribute stuff to the script classpath dynamically as they execute.

1. is just too complicated to get right, except perhaps for top-level ‘apply’ statements early in the script (which they often are). So we could extract only a certain subset of ‘apply’ statements, for example, perhaps these are ok:

apply plugin: “group:module:version:plugin”

subprojects {

apply plugin: “group:module:version:other-plugin”

}

1. doesn’t necessarily have to be as complex as it is now. For example, perhaps ‘apply’ statements in the ‘buildscript { }’ block contribute to the script classpath, and those outside the ‘buildscript { }’ block do not:

buildscript {

apply from: “group:module:version:plugin”

subprojects {

apply from: “group:module:version:other-plugin”

}

}

However, to me, 3) is the way to go, perhaps combined with 2) for those cases where it really does make sense.

So, given this, I would have ‘apply’ create an isolated classloader for the plugin, with some caching so that we reuse the classloader across build scripts.

---

<div class="post-metadata">

**Author:** ![curious\_attempt\_bunn](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/curious_attempt_bunn/32/120_2.png) [@curious\_attempt\_bunn](https://discuss.gradle.org/u/curious_attempt_bunn)\
**Post date:** [January 17, 2012, 10:47pm UTC](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568/20 "2012-01-17T22:47:00Z")

</div>

Thanks, Adam.

So if we go with 3), how do we make plugin Types available to the build script? E.g. the Xslt task: [http://wiki.gradle.org/display/GRADLE/Plugins#Plugins-XsltPlugin](http://wiki.gradle.org/display/GRADLE/Plugins#Plugins-XsltPlugin)

Would that be a scenario in which we would use 2) ?

[Next page](https://discuss.gradle.org/t/plugin-portal-improving-plugin-development/568.md?page=2)
