On 18/07/2011, at 10:42 AM, Luke Daley wrote:

> 
> On 17/07/2011, at 9:32 AM, Eric Berry wrote:
> 
>> I've run into this issue myself. Right now I'm having our developers 
>> download the plugin jar file and install it into gradle lib/plugins 
>> directory. But the buildscript method seems pretty standardized.
>> 
>> I wonder if it could be automated more by adding something like:
>> apply plugin: 'company-plugin', fromJar: 'url://to/company-plugin.jar'
>> 
>> I was looking through the source recently, and I was thinking it might be 
>> possible to add something like this to the DefaultObjectConfigurationAction.
>> 
>> Where it would download the jar to ~/.gradle/cache (or somewhere else), and 
>> then add a buildscript closure to the project pointing the dependency at the 
>> downloaded jar file.
>> 
>> Afterwards applying the plugin.
>> 
>> I'm not completely familiar with the Gradle source, but is something like 
>> this even feasible? If so, I can try and get something working over the next 
>> week or so and try to submit a patch?
> 
> This thread and the “easy plugin integration” thread are highlighting that 
> there is a hole here.
> 
> Before working on any implementations or even DSL modifications, I think we 
> need more thought and exploration of the core problem here. The best way to 
> do that is probably to explore people's use cases and see what patterns 
> emerge.


As I see it, the basic problem here is that organisations need to make some 
build logic available to their teams, in a controlled way. The exact build 
logic that needs to be shared varies, but generally includes:

* Information that the build needs to know about the organisation's 
infrastructure. For now, this means repository definitions, but might later 
include things such as resources for distributed build/test or deployment.

* Configuration of the standard Gradle plugins, to define the organisation's 
convention. For example, changing the default source directories.

* Making custom plugins available to the build.

The idea is that it should be possible to inject this logic from a single 
place, rather than spreading it out over a bunch of places. I think it is also 
important that as little boiler-plate as possible is required to inject the 
logic, and to use the custom plugins. Ideally, you'd use the same dsl to use 
the custom plugins as you would for the standard Gradle ones.

Some possible approaches:

You could to inject the logic from the root project. The logic could be 
packaged up into an external script:

apply from: "http://some-server/some-logic/1.2/bootstrap.gradle";

This would be able to inject buildscript { } stuff into the build scripts of 
child projects. But it wouldn't work for external scripts, or the build script 
of the root project. You could always do:

buildscript {
    apply from: "..."
}

But this doesn't work for buildSrc projects, which probably need to use the 
same logic. You'd have to include the above snippet in buildSrc/build.gradle, 
and keep it in sync with the root project.

Finally, it also doesn't help with logic that might be required in the 
settings.gradle.

We really need some point in time before these where we can inject the logic.

So, another approach would be to use an init script (*). But this means either 
installing the init script on every machine which needs to run the build, or 
checking in the init script and requiring everyone that uses the build 
(including IDEs via the tooling api) with the appropriate -I flag. These are 
both non-starters, I think.

To address this, we could add some more conventional places where we look for 
an init script. For example, we could look for $rootDir/init.gradle, and apply 
it if we find it. The problem with this is that we don't know $rootDir until 
after we've built buildSrc and executed settings.gradle. So this is no good. I 
think $cwd/init.gradle is no good, either, as $cwd could be anything.

When we're using the wrapper, we do know $rootDir very early in the execution. 
So, we have some options here. For example, the wrapper could look for, say, 
$rootDir/init.gradle or $rootDir/gradle/init.gradle, and pass them through to 
Gradle. The init script could then be checked in, and delegate to an external 
script:

apply from: "http://some-server/some-logic/1.2/bootstrap.gradle";

There are a couple of problems with this approach. First, it doesn't work if 
someone happens to run the build using an installed Gradle distribution, rather 
than running ./gradlew, which is an easy enough 'mistake' to make. I think we 
can solve this by making the 'gradle' command wrapper aware. That is, we change 
the Gradle distribution that you download and install so that it contains just 
the wrapper. This way, however you invoke Gradle - installed distribution, via 
the tooling API, or via ./gradlew, you always get the same behaviour. I think 
this is a good change to make regardless of what we decide to do regarding 
bootstrap logic.

The second downside to the checked-in init script approach is that it is quite 
awkward to actually develop and change the logic. You have to either embed some 
logic in the checked-in script which decides whether to use a local development 
version or the real published version, which is a bad idea if this logic needs 
to end up in many projects, or you need to publish development versions of the 
init script to your repository so you can test them. Either way, it's a burden 
for those who have to maintain and roll out this organisation wide logic.

So, another conventional location we could use is either: relative to the 
target Gradle distribution that the wrapper downloads, or embedded in the 
distribution itself. Embedding the logic is interesting, in that you can 
download and install the distribution manually and the logic still works.

Another option is to include an optional property in gradle-wrapper.properties 
which can point to an init script for the wrapper to download and apply.


* We'd have to fix the init script mechanism so you can mess with the buildSrc 
project from the init script. There's a patch from Fred to fix this but it 
needs a few tweaks before we apply it.


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Reply via email to