How to Run Custom Gradle Task In Gradle Plugin During Android Project Configuration Phase?

Problem Statement: I have multiple android projects that all require the same pre-configuration. This includes declaring maven repositories, setting versionCodes and versionNames, and other misc configuration items. The same blocks are copy and pasted in every project or placed in a local common.gradle file and then applied and called at the project level build.gradle configuration stage.

My Solution: Extract all of this common logic into a standalone gradle plugin and let each projects build.gradle file apply this plugin to receive these configuration events.

I created a standalone plugin, did an override on plugin and it looks something like this:

class CommonManager: Plugin<Project> {
    override fun apply(target: Project) {
        println("APPLY FUNCTION HAS BEEN ENTERED")
        target.tasks.create("myPluginTask", ReleaseManager::class.java)
    }

The ReleaseManager class is a class that extends DefaultTask and creates a task to run. This is what is recommended in the gradle docs and it makes sense from a testability / reusability standpoint and that class looks something like this:

abstract class ReleaseManager: DefaultTask() {
    @get:Input
    abstract val versionHistoryPath: Property<String>

    @TaskAction
    fun configureVersionsAndReleaseMeta() { // do work... }

According to the docs I have read and other example projects I have thumbed through, this is set up correctly. I built the plugin using java-library instead of java just to have a local .jar file to point to in my android projects for quick testing. An example of one of these build.gradle files looks like the following:

buildscript {

    repositories {
        google()
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }

    dependencies {
        // misc dependencies ...
        classpath files("libs/MyCustomPlugin-1.0-SNAPSHOT.jar")
    }
}


apply plugin: "com.myplugin.common"

myPluginTask {
    versionHistoryPath.set("sdk/version_history.txt")
}

subprojects {
    apply plugin: 'maven-publish'
    apply plugin: 'com.jfrog.artifactory'
    group = 'org.jfrog.test.gradle.publish'
}

I create a dependency on the .jar and apply the plugin, then configure the task with the property it needs to run. However, the task never runs during the configuration phase when the log outputs > Configure project I see my print statement from the apply function in my plugin log but no output or configuration happens in the task class that I defined. If I click the play arrow next to the myPluginTaks{} configuration definition, it does in fact run fine. At this point, I know I’m pointing to the .jar correctly, I can access the task that I create in my plugin class, and I can set its property respectively. I’m newer to doing this kind of custom work with gradle and want to understand what I am doing wrong. Let me outline my thought process and debugging steps I have tried.

My “Bug” Statement: I want the task "myPluginTask" to execute after I apply my plugin in my build.gradle script and I have configured the task with the proper input. It is currently not executing the task.

Thoughts and notes:

  • I used create over register in the plugin apply function when creating my task. My understanding is that by using create, I am saying “hey I want to create a task, and I want the build to know about it immediately” rather than “Hey here’s a task definition, but lets lazy load it once it is actually invoked on the implementation end”

  • I moved the implementation of ReleaseManager into the plugin class as individual functions and called these functions inside the task creation closure. That works. To my understanding this is because anything defined in there is run during a builds configuration phase. I can defer this to the execution phase with a doFirst or doLast closure if I wanted to.

  • My hunch is, I’ve created a task and sure the build now knows about it immediately, but it has no plans on executing the task until at least the execution phase and needs a trigger. Whether that trigger is a direct invocation of the task or the task depends on a task that is going to run in the execution phase.

Any help would be greatly appreciated. Happy to provide any additional information if needed.

1 Like