GradleLauncher run() method not working with multi project build

I am trying to write an integration test for one of my plugins. The plugin adds functionality to create a jar of all the .class files of all subprojects. I am trying to use GradleLauncher.newInstance(startParameter) to run the build, but it seems to not be adding the sub projects to the root project it is running the tasks against. Here is the settings.gradle file of the project I am launching:

new File("$settingsDir/components/").eachDir {
 include it.name
}
  rootProject.name = "jumboJar"
println rootProject.children
  rootProject.children.each { project ->
    String projectDirName = "components/${project.name}"
    project.projectDir = new File(settingsDir, projectDirName)
    project.buildFileName = "${project.name}.gradle"
}

And I am launching it like this:

def project = ProjectBuilder.builder().withProjectDir(projectDir).build()
  def runTasks(Map<String, Object> args, List<String> tasks) {
    def startParameter = project.gradle.startParameter.newBuild()
    startParameter.setGradleUserHomeDir(new File('userHome'));
      startParameter.projectDir = project.projectDir
    if (args.buildScript) {
      startParameter.buildFile = new File(project.projectDir, args.buildScript)
    }
    if (args.settingsFile) {
      startParameter.settingsFile = new File(project.projectDir, args.settingsFile)
    }
    startParameter.taskNames = tasks
    def launcher = GradleLauncher.newInstance(startParameter)
      println "BEFORE LAUNCH"
    def result = launcher.run()
    println "AFTER LAUNCH"
    result.rethrowFailure()
  }

When I run the ‘:clean, :projects’ tasks, I get the following output:

BEFORE LAUNCH
[:sub1, :sub2] //println from settings.gradle file
:clean
  UP-TO-DATE
  :projects
    ------------------------------------------------------------
Root project
------------------------------------------------------------
    Root project 'jumboJar'
No sub-projects
    To see a list of the tasks of a project, run
gradle
  <project-path>:tasks
  For example, try running
gradle
  :tasks
    BUILD SUCCESSFUL
    Total time: 3.554 secs
AFTER LAUNCH

So you can see from the println statement from the settings file that it is picking up the subprojects of the build and adding it to a Project, but it seems that when it runs the tasks it is against a different object because it says it has no subprojects.

Thank you,

Jeremy

The output looks strange, but since ‘GradleLauncher’ is known to work for multi-project builds, my best guess is that something is wrong with your logic (although I can’t spot it). I recommend to start with the simplest possible setup and slowly build it up. Instead of ‘ProjectBuilder’ (which is only meant to be used for unit testing) you can use ‘new StartParameter()’.

Thanks for the response Peter, I tried a couple different ways to get it to run using GradleLauncher.newInstance(startParameter), but could not get it to work with a multi-project build. I ended up using http://www.gradle.org/docs/current/groovydoc/org/gradle/tooling/BuildLauncher.html#run() instead and that seems to be working with multi-project.

I don’t understand what you did differently to get it to work. Anyway, good to hear that you were successful.

Hallo Jeremy,

could you post your solution there. I’m trying to write a unit test for my gradle plugin that executes gradle task.

Thanks in advance.

Hi Mikhail,

I used this project as an example to write integration tests for my plugins: https://github.com/jvoegele/gradle-android-plugin

But instead of using

GradleLauncher.newInstance(startParameter)

in the TestProject class (https://github.com/jvoegele/gradle-android-plugin/blob/master/src/integTest/groovy/com/jvoegele/gradle/android/support/TestProject.groovy) I used:

def runTasks(String[] tasks) {
        def connection = GradleConnector.newConnector().forProjectDirectory(projectDir).connect();
        try {
            def build = connection.newBuild()
                          build.forTasks(tasks)
            build.withArguments()
            build.run()
        } catch (Exception e) {
            throw new GradleConnectionException("Build execution failed.", e);
        } finally {
            connection.close();
        }
    }

because I could not get the other method to work with my multi-project setup.

Hope this helps,

Jeremy