Search code examples
javagradlegradle-task

Why gradle tasks doesn't run in proper order


I have java project with 2 subprojects. With structure like this

- project_root
  |- client
     |- src
     |- build.gradle
  |- server
     |- src
     |- build.gradle
  |- build.gradle

All I need is to create 'deploy' task in root buiild.gradle with next actions:

  • clean all subprojects
  • clean 'target' folder
  • make jars for all subprojects
  • copy jars from all subprojects to folder 'target' in root
  • make an archive of the target folder.

This is how I try to do this

root build.gradle:

allprojects {
    apply plugin: 'java'
    repositories {
        mavenCentral()
    }
}

task cleanTarget(type: Delete) {
    delete "target"
    delete "target.zip"
}

task cleanAll() {
    dependsOn cleanTarget
    dependsOn clean
    dependsOn subprojects.clean
}

task jarChilds() {
    dependsOn subprojects.jar
}

task copyFiles(type: Copy) {
    copy {
        from("client/build/libs/")
        into project.file('target')
    }
    copy {
        from("server/build/libs/")
        into project.file('target')
    }
}

task zipApp(type: Zip) {
    from 'target/'
    include '*'
    include '*/*'
    archiveName 'target.zip'
    destinationDir(project.rootDir)
}

task deploy{
    dependsOn cleanAll
    dependsOn jarChilds
    dependsOn copyFiles
    dependsOn zipApp
    jarChilds.shouldRunAfter cleanAll
    copyFiles.shouldRunAfter jarChilds
    zipApp.shouldRunAfter copyFiles
}

Every task runs properly if I manually run it, but if I run 'deploy' folder 'target' didn't create. Here is log output:

Executing task 'deploy'...

> Task :clean
> Task :cleanTarget
> Task :client:clean
> Task :server:clean
> Task :cleanAll
> Task :client:compileKotlin
> Task :client:compileJava
> Task :client:processResources
> Task :client:classes
> Task :client:inspectClassesForKotlinIC

> Task :client:jar
Client jar done

> Task :server:compileKotlin
> Task :server:compileJava
> Task :server:processResources
> Task :server:classes
> Task :server:inspectClassesForKotlinIC

> Task :server:jar
Server jar done

> Task :jarChilds
> Task :copyFiles NO-SOURCE
> Task :zipApp NO-SOURCE
> Task :deploy


BUILD SUCCESSFUL in 3s
14 actionable tasks: 14 executed
12:39:15: Task execution finished 'deploy'.

I see that error "NO-SOURCE", but folders 'client/build/libs' and 'server/build/libs' exist and contain jars. I can be sure because the manual running task 'copyFiles' create folder 'target' and copy all files. The only possible option that I see is 'copyFiles' task running before 'jarChilds'. But I don't understand why. What am I missing, why is it not working?

P/S/ Sorry for my bad English


Solution

  • Your task copyFiles uses the method copy of the Project instance instead of configuring the actual task. This is the reason why the task stays unconfigured and, once it is executed, reports that there are no files to process (NO-SOURCE). To configure your task, use methods of the task type Copy:

    task copyFiles(type: Copy) {
        from("client/build/libs/")
        from("server/build/libs/")
        into("target")
    }
    

    Additional hint: You probably do not need your task copyFiles at all. Instead, you may just use the task zipApp to collect the files:

    task zipApp(type: Zip) {
        from subprojects.jar
        archiveName 'target.zip'
        destinationDir(project.rootDir)
    }
    

    By putting the jar tasks of the subprojects into the from method, Gradle will even add the task dependencies automatically, so you won't need to register them using dependsOn.

    Check out the following short and complete build.gradle file:

    subprojects {                    // using subprojects here, because your root project has no sources
        apply plugin: 'java'
        repositories {
            mavenCentral()
        }
    }
    
    task clean(type: Delete) {       // without the 'java' plugin, there is no automatic 'clean' task
        dependsOn subprojects.clean
        delete 'target.zip'
    }
    
    task zipApp(type: Zip) {
        mustRunAfter clean
        from subprojects.jar
        archiveName 'target.zip'
        destinationDir(project.rootDir)
    }
    
    task deploy {
        dependsOn clean
        dependsOn zipApp
    }