gradlepluginsmulti-projectbuild-scriptgradle-multi-project-build

gradle custom task class makes itself uncompilable


I'm trying to write a custom Gradle task class and use it in another subproject. I'm having problems tying the build together.

In this example, I have named the subprojects "a" (for application) and "p" (for plugin, although I'm not using a plugin object but just providing a task class to the build script).

settings.gradle

include 'p'
include 'a'

p/build.gradle

apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven-publish'

group 'test'
version '1.0'

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

dependencies {
    implementation gradleApi()
    implementation localGroovy()
}

p/src/main/groovy/p/MyTask.groovy

package p

import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;

class MyTask extends DefaultTask {
    @TaskAction
    void run() {
        System.out.println('yay!');
    }
}

a/build.gradle

buildscript {

    repositories {
        mavenLocal()
    }

    dependencies {
        classpath 'test:p:1.0'
    }

}

group = 'test'
version = '1.0'

apply plugin: 'java'

task myTask(type: p.MyTask) {
}

The "plugin" is built by running, inside the p folder:

../gradlew clean build publishToMavenLocal

Inside the a folder:

../gradlew myTask

prints "yay!"

However, while developing, bugs happen. When I simulate a bug in MyTask:

MyTask() {
    throw new RuntimeException("an error");
}

and build the plugin (in folder p):

../gradlew clean build publishToMavenLocal

it fails as expected.

Now I "fix" the bug by removing the broken constructor again, and rebuild in folder p:

../gradlew clean build publishToMavenLocal

but this command fails with the same error.

As far as I understand, the reason is that:

To verify, I comment out the include line for a in settings.gradle, and it works again. Reverting settings.gradle, and it still works, because now the "fixed" plugin is in my maven repo, and rebuilding the plugin will just overwrite it again with the working version.

The bottom line is that bugs in my custom task class (or custom plugin, or any other buildscript code) have the potential to make themself un-compilable, with the workaround being to edit or temporarily rename settings.gradle. The more complex the project gets, the more cumbersome this becomes: Renaming does not work if the plugin code itself contains multiple subprojects, and even commenting out becomes "commenting out the right lines".

What is the intended way to fix this problem?


Solution

  • Complex logic for a single (multi-) project is best organized in buildSrc. You can for the most part regard it as a normal sub-project but just for the build classpath instead. Plugins and tasks that you create here are automatically available for all projects in the multi-project.

    If, for some reason, you rather continue to work with a local Maven repository, you could think about publishing stable releases of the plugin with a version number so it is easier to roll back.