How to share a common build.gradle via a repository?

16,417

Solution 1

My current solution is option 3; package the common scripts into a jar as resources and then unjar during the buildscript section like so

buildscript {
    repositories {
        // enterprise repo here
    }
    dependencies { 
        classpath 'com.foo.bar:common-build:0.1.0-SNAPSHOT'
    }
    dependencies {
        ant.unjar src: configurations.classpath.singleFile, dest: 'build/gradle'
    }
}

apply from: 'build/gradle/common.gradle'

This seems to do what I want.

Solution 2

There are two possibilities:

  1. Publish a build script to a web server, and include it with apply from: "http://path/to/script.gradle"

  2. Write a Gradle plugin, publish it as a Jar to a Maven or Ivy repository, and include it with:

    buildscript {
        repositories { .. }
        dependencies "mygroup:myplugin:1.0"
    }
    
    apply plugin: "myplugin"
    

The second option is more complicated, but also somewhat more powerful. For example, plugin Jars will be cached, whereas remote build scripts currently won't. In general, I recommend to start with 1., and move to 2. if and once it becomes necessary. In the future, Gradle will likely offer a mechanism which combines the ease of use of 1. with the advantages of 2.

Solution 3

Buildings on Matt’s solution, I find the following to be a bit cleaner:

buildscript {
  repositories {
    <your repos>
  }
  dependencies {
    classpath '<your jar>'
  }
}

afterEvaluate { project -> // afterEvaluate for resolving the build script dependency
  apply from: project.buildscript.classLoader.getResource('path/to/your/resource/in/the/jar').toURI()
}

Just my two cents. :-)

Solution 4

I have an answer and another question:

First, to access a shared file from a repository (i.e. Nexus) you can build a URL that includes a query:

apply from: 'http://server-url/nexus/service/local/artifact/maven/redirect?r=repository-name&g=group-name&a=build-common&e=gradle&v=LATEST'

I did this for our project and it works great. I can manage the 'build-common.gradle' file in a separate SVN project and upload it to Nexus as a SNAPSHOT. The above URL (with appropriate values inserted for 'server-url', 'repository-name', and 'group-name') finds the latest SNAPSHOT of my .gradle script I uploaded. No need to package it in a jar.

Solution 5

My version:

repositories {  
    <your repos>
}  
configurations {   
    scripts   
}  
dependencies {  
    scripts group: 'org.foo', name: 'build', version: '1.0.0', ext: 'gradle' 
    // add more scrips if needed 
}  
configurations.scripts.resolve().each { apply from: it }
Share:
16,417

Related videos on Youtube

Matt
Author by

Matt

Updated on June 15, 2022

Comments

  • Matt
    Matt almost 2 years

    I'm looking at porting a maven build to gradle. One feature of maven is pom inheritance whereby I can declare a variety of common behaviour in a pom, publish that to a repository and then use that via the <parent> element in a concrete project.

    My Q is simply whether there is an equivalent behaviour in gradle?

    I've previously done this in ant+ivy by importing a common build.xml which relied on either having already checked out the location of the common build.xml from source control or using something like svn:externals. I can repeat this approach without any real difficulty but this seems to be one thing maven does quite nicely so it would be nice to see something similar in gradle.

  • Matt
    Matt about 12 years
    is it possible to publish the shared build.gradle to a repository by packaging it as a plugin or just publish plugins that do stuff to a project? I can't see any examples of how to do the former and it's not obvious how one would do that.
  • Peter Niederwieser
    Peter Niederwieser about 12 years
    You can publish a build script to a web server/repository accessible via HTTP, or publish a plugin to a repository. The latter is a class implementing the Plugin interface packaged as a Jar. The user guide explains how the latter is done.
  • Peter Niederwieser
    Peter Niederwieser about 12 years
    That's quite a hack. What do you hope to gain from it?
  • Matt
    Matt about 12 years
    I'm not quite sure whether I should be proud at my creativeness or disgraced by my hackery. The gain is an obvious (to me) way to share a specific version of a common build that defines a standard way for a closely related (but not part of the same multiproject build) set of projects to be built. I've reduced a previous homegrown convention based ant+ivy build (that comes in at a few thousand lines of xml + all the module specific ivy.xml's) down to a few hundred lines of a common build script (that mostly deals with a v specific part of that build & has the standard deps) so I'm quite happy.
  • Matt
    Matt about 12 years
    fwiw the above approach was good for prototyping but it has ultimately stabilised to a few plugins.
  • JARC
    JARC over 11 years
    I guess this saves you having to host the script on a web server. Might try this.
  • László Papp
    László Papp about 10 years
    Please post only the answer part as answer.
  • Carl Pritchett
    Carl Pritchett over 9 years
    I like that this still keeps files in a jar rather than unjaring but also allows gradle script files to be used. It would be time consuming to convert all my current scripts to plugins (or is it easier than I think?).
  • Patrick Bergner
    Patrick Bergner over 9 years
    It's dead easy to write an own plugin, mainly just specific locations and packaging plus a simple descriptor. See 58.5 on gradle.org/docs/current/userguide/custom_plugins.html
  • Blundell
    Blundell over 9 years
    @PeterNiederwieser I find apply from: url only works with http not https , is this documented?
  • Igor Čordaš
    Igor Čordaš over 8 years
    This seems like a good solution but I keep getting Error:(218, 0) Could not read script 'jar:file:/...' Is there some reason why this is happening?
  • Yngvar Kristiansen
    Yngvar Kristiansen almost 7 years
    If anyone cares to do it, option number two should be expanded with how to do it, or even better, existing source code that does this. I tried doing it, and it is not straight forward for someone new to Gradle.
  • Ben
    Ben over 6 years
    I wish this was working in settings.gradleduring initialization but I get Error:Cause: org.gradle.initialization.DefaultSettings_Decorated cannot be cast to org.gradle.api.Project
  • Tomas Bjerre
    Tomas Bjerre over 6 years
    This works great with jitpack, here is an example github.com/tomasbjerre/gradle-scripts
  • Tomas Bjerre
    Tomas Bjerre over 6 years
    afterEvaluate is a bit risky as the applied script may cause afterevaluate to be invoked again. And there will be a loop. github.com/researchgate/gradle-release/issues/237
  • Brice
    Brice about 6 years
    This solution fails when there's multiple dependencies in the build script
  • Brice
    Brice about 6 years
    That works even with additional dependencies, thanks !