Gradle and the “Parent Pom”

Coincidentally, something came up I wanted to blog about, and it turns out it’s a follow up to the last blog post I wrote 9 months ago.

I’ve been increasingly unhappy with using “apply from” to apply a script plugin from a hard coded location. It’s no use if you’re offline, or not on the right VPN to access the file, or whatever. What I didn’t realise is that I could do apply all the same configuration defaults from a binary plugin. Then you get proper dependency management like you would with a Maven parent pom.

Here’s the code for the Plugin, which is just a standard gradle plugin

import org.gradle.api.Project
import org.gradle.api.Plugin
import org.apache.log4j.Logger
import org.gradle.api.GradleException

public final class CommonConfigPlugin implements Plugin<Project>{

    @Override
    void apply(Project project) {
        addDependencies(project)
        applyPlugins(project)
        configureReleasePlugin(project)
    }
    
    private void configureReleasePlugin(Project project) {

        if (!project.parent) {
            project.createReleaseTag.dependsOn { project.allprojects.uploadArchives }
        }

        //do this for all projects
        project.uploadArchives {
            ... config here ...
        }               
    }

    private void addDependencies(Project project) {
        project.afterEvaluate {            
            project.dependencies.add("testCompile", "junit:junit:4.11")
            project.dependencies.add("compile", "log4j:log4j:1.2.14")
        }
    }

    private void applyPlugins(Project project) {
        project.configure(project){
            apply plugin: 'java'
            apply plugin: 'maven'               
        }

        //apply these to parent project only
        if (!project.parent) {
            project.configure(project){
                apply plugin: 'sonar-runner'
                apply plugin: 'release'
            }
        }
    }
}

Then in the main build.gradle file for any project, I add the jar as a dependency and apply the plugin.

allprojects {
    repositories {
        mavenLocal()
        maven { url "http://my.repo"}
    }
    apply plugin: "my-common-config"

}
buildscript {

    repositories {
        mavenLocal()
        maven { url "http://my.repo"}
    }
    dependencies {
        classpath 'uk.co.anorakgirl.gradle:my-common-config-plugin:1.0.0'
    }
}

Any dependencies which the plugin has end up as dependencies in the buildscript of the project, meaning I don’t have to repeat the dependency on the release plugin, because my common config plugin already depends on it.

I’m going to put more in this common-config-plugin.

  

5 thoughts on “Gradle and the “Parent Pom”

  1. Awesome blog, I love Gradle and I’ve been looking around to find Gradle equivalents of Maven features that I rely on, one of which is the parent pom. Your article got me thinking though that writing plugins this way is a bit of a learning curve for a lot of people, so I created the gradle-pater-builld-plugin to allow the configuration of a gradle build using a normal gradle build file. It basically does gradle build file discovery from the classpath and programatically does the “apply from”, this means that you can take advantage of the dependency management like any normal library. It would be cool if you could take a look and let me know what you think.

    gradle-pater-build-plugin

  2. Hi, good article, I’ve been trying to do something similar for our organisation. I notice you only use the Java Plugin, have you any need to use the War Plugin? We have a number of in-house developed JAR libraries and WAR applications. I have created a custom plugin along the lines of what you’ve detailed above, but need it to work for both JAR/WAR files. If I only use the War Plugin, the JAR files are created as WAR files, is this a problem you have any experience with?

  3. Do you have a working GIT repo (or other) with this working? I tried this myself and while I can get it working by adding:

    plugins {
    id ‘net.researchgate.release’ version ‘2.0.2’
    }

    or

    buildscript {
    repositories {
    jcenter()
    }
    dependencies {
    classpath ‘net.researchgate:gradle-release:2.0.2’
    }
    }
    apply plugin: ‘net.researchgate.release’

    to my build.gradle file for a single project, I cannot get it to work when adding it to the binary plugin!! It complains that it cannot find the plugin, I created a topic on the Gradle Forum for this:

    http://discuss.gradle.org/t/plugins-config-block-in-a-custom-gradle-plugin/8987

    Yours is the only partial code example I’ve come across and hoped you’d be prepared to allow access to a public working example?

    I’m using Gradle 2.2.1

  4. I have the townsfolk release plugin as a dependency in the common config plugin in both the buildscript block so I can apply it and use it to release the plugin, and in the main dependencies block – his means that projects which use the plugin get it as a dependency too. Then in the binary plugin I am just applying it as in the original blog post. It works fine for me – sorry I can’t share the code at the moment as it is a work repository. I am using an older version of the release plugin – com.github.townsfolk:gradle-release:1.2.

Leave a Reply

Your email address will not be published. Required fields are marked *