Gradle's mustRunAfter/finalizedBy only for a specific task?

Viewed 13083

I'm trying to get Gradle's mustRunAfter and finalizedBy to work only for a specific task. Take this example build.gradle:

task removeTestDatabaseContainer {
  doLast {
    println '\ninside removeTestDatabaseContainer\n'
  }
}

task startTestDatabaseContainer {
  doLast {
    println '\ninside startTestDatabaseContainer\n'
  }
  finalizedBy removeTestDatabaseContainer
}

task flywayMigrate { t->
  doLast {
    println '\n inside flywayMigrate\n'
  }
}

task flywayClean { t->
  doLast {
    println '\n inside flywayClean\n'
  }
}

task testEverything {
    dependsOn startTestDatabaseContainer
    dependsOn flywayMigrate
    dependsOn flywayClean

    flywayMigrate.mustRunAfter startTestDatabaseContainer
    flywayMigrate.finalizedBy flywayClean

    flywayClean.mustRunAfter flywayMigrate
    flywayClean.finalizedBy removeTestDatabaseContainer
}

I'm happy with how testEverything works. I want the output I'm getting from that task:

āžœ  gradle testEverything
Parallel execution is an incubating feature.
:startTestDatabaseContainer

inside startTestDatabaseContainer

:flywayMigrate

 inside flywayMigrate

:flywayClean

 inside flywayClean

:removeTestDatabaseContainer

inside removeTestDatabaseContainer

:testEverything

BUILD SUCCESSFUL

Total time: 0.597 secs

However, when I run only flywayMigrate I get unexpected problems. This is the output:

āžœ  gradle flywayMigrate                
Parallel execution is an incubating feature.
:flywayMigrate

 inside flywayMigrate

:flywayClean

 inside flywayClean

:removeTestDatabaseContainer

inside removeTestDatabaseContainer


BUILD SUCCESSFUL

Total time: 0.605 secs

This is not the output I want. I would like only flywayMigrate to run. Question 1) How can I make testEverything work as it does and at the same time have gradle flywayMigrate invoke only the flywayMigrate-task?

Question 2)
I'm told this has something to do with the fact that everything inside the brackets of task testEverything {} is configuration, which is always processed by Gradle. So any mustRunAfter/finalizedBy I set within a task will have "global effect". But in that case, why doesn't gradle flywayMigrate invoke startTestDatabaseContainer? (Because of the line flywayMigrate.mustRunAfter startTestDatabaseContainer inside the testEverything task.)

Edit: I was directed to Ordering tasks and Finalizer tasks in the Gradle documentation and they answer question 2: mustRunAfter only takes effect when both tasks are ran. finalizedBy on the other hand takes effect when only the task it is set on is ran. That answers why flywayClean and removeTestDatabasContainer are ran when I execute gradle flywayMigrate.

I'm still struggling to make gradle testEverything work as it does above and at the same time get gradle flywayMigrate to just execute flywayMigrate.

1 Answers

Thanks to the help of eskatos on #gradle on Freenode I found a solution. It was simply to remove the finalizedBy-lines i had. Updated build.gradle that works:

task removeTestDatabaseContainer {
  doLast {
    println '\ninside removeTestDatabaseContainer\n'
  }
}

task startTestDatabaseContainer {
  doLast {
    println '\ninside startTestDatabaseContainer\n'
  }
  finalizedBy removeTestDatabaseContainer
}

task flywayMigrate { t->
  doLast {
    println '\n inside flywayMigrate\n'
  }
}

task flywayClean { t->
  doLast {
    println '\n inside flywayClean\n'
  }
}

task testEverything {
    dependsOn startTestDatabaseContainer
    dependsOn flywayMigrate
    dependsOn flywayClean

    flywayMigrate.mustRunAfter startTestDatabaseContainer
    //flywayMigrate.finalizedBy flywayClean

    flywayClean.mustRunAfter flywayMigrate
    //flywayClean.finalizedBy removeTestDatabaseContainer
}
Related