I have been struggling with finding a good way of calling a task twice with different configuration


(Flemming Harms) #1

Hello,

I have been struggling with finding a good way of calling a task twice with different configuration. I eventual come up with a “workaround” but feel it’s rater complicated consider I “just” want to call a task twice with different configuration.

Background info:

I’m using flyway gradle plugin to roll out database DDL and first step is to create the database schema with a system user, and second step is to roll out the rest of the DDL with the local user. So basic I want the task dbBootstrap to call dbCreateSchema and flywayMigrate with the sys configuration and then call flywayMigration with the default settings.

flyway {
locations = flywayLocations
url = flywayUrl.toString()
user = flywayDbuser.toString()
password = flywayDbpassword.toString()

}

task sysdbInit(group: ‘database’){
doFirst {
project.ext[‘flyway.user’] = 'systemuser as sysdba’
project.ext[‘flyway.password’] = '****'
project.ext[‘flyway.locations’] = flywayCreateSchemaLocation
}
}

task dbCreateSchema(group: ‘database’, dependsOn: [‘sysdbInit’,‘flywayMigrate’]) {
flywayMigrate.mustRunAfter sysdbInit
mustRunAfter clean
}

task dbBootstrap(group: ‘database’, dependsOn: [‘dbCreateSchema’,‘flywayMigrate’]) {
mustRunAfter clean
}

As I understand gradle doesn’t allow to add the same task twice or more to the call tree, so as a workaround I created two gradle files. One have the dbCreateSchema and the sysdbInit task and the other has the dbBootstrap and default configuration

My script look like this:

task dbCreateSchema(type: GradleBuild, group: ‘database’) {
buildFile = "flywaydb-schema.gradle"
tasks = [‘dbCreateSchema’]
}

task dbBootstrap(group: ‘database’, dependsOn: [‘dbCreateSchema’,‘flywayMigrate’]) {
mustRunAfter clean
}

Is this the best way to solve this?

Thanks!

/Flemming


(Benjamin Muschko) #2

The plugin hasn’t necessarily been designed in a way that would make it easy for you. It already creates task instances out-of-the-box though your use case looks slightly different. What you want is to create task instances of a specific task type yourself. So what the plugin should provide is a separation of capabilities and conventions. Sounds fairly abstract - I know. I am currently working on a guide that clearly describes those techniques. It’s a really a shortcoming of our documentation that plugin authors don’t know about the concept. I will add a link to this post when it’s published.

Here’s what you can do in the meantime:

Create the task instance you need yourself with a specific type. Those custom task types are unfortunately not well documented by the plugin but you can find them in plugin repository.

For example:

import org.flywaydb.gradle.task.FlywayMigrateTask

task a(type: FlywayMigrateTask) {
    // configure task
}

task b(type: FlywayMigrateTask) {
    // configure task
}

As you can see you now got two tasks of the same type that can be configured differently but execute the same functionality.


(Flemming Harms) #3

Thanks for taking the time to look into this

This solution seems much more elegant than my work around.

/Flemming


(Benjamin Muschko) #4

As promised we published two new guides that go into the details of designing and implementing plugins:

I hope you’ll find them useful. The guides should give you more information on how solve certain problems. There are more guides in the pipeline. Periodically check the guides section on gradle.org. Feedback welcome!