kjerins
kjerins

Reputation: 433

How to run Flyway migrations from a Gradle dependency?

I've got two Spring Boot webservices that must both use the same database, same schema and same tables - one service reads from the tables, the other writes to them. Right now one of the services is in development and works with an in-memory DB instead of the real DB, so I can have each service contain its own copy of the database migrations. Once both services are working with the same DB, that won't work - the first one that gets started will run its migrations and the other one will fail. But both projects still have to have the migrations, because they're needed to create in-memory databases for automated tests.

As a solution, I'm making a third project whose only responsibility would be to run the migrations, and both original applications would pull the migrations from this new one, but I'm stuck on how to make that happen.

The closest thing to what I need that I've seen is this code from another SO question:

sourceSets {
    main {
        resources {
            srcDirs += [
                project(':data').sourceSets.main.resources
            ]
        }
    }
}

But this is for including resources from another local project, not from a gradle dependency. I've got my private Maven repo listed and the dependency resolved, but I'm stumped on what to write instead of the inner line of that block above.

repositories {
    mavenCentral()
    maven {
        url "http://my.repo.link/"
    }
}

dependencies {
    // other dependencies 
    runtime 'my.group:database-project:1.0'
}

Upvotes: 2

Views: 3192

Answers (1)

Bjørn Vester
Bjørn Vester

Reputation: 7608

If you are using a Gradle multi-project layout and you like to use the Flyway plugin, I guess you can just configure the migration folder directly. Something like this:

flyway {
  locations = ["filesystem:$rootDir/data/migrations"]
}

If you are using stand-alone projects, you can package your migrations into a jar file using the java plugin, publish it to a Maven repository and make a normal dependency to that. If you don't want to put your migrations on the application classpath, you can put the dependency in a custom configuration. And if you have a non-standard folder structure, you can configure that through a classpath: value in the locations parameter. Something like this:

configurations {
    flywayMigration
}

dependencies {
    flywayMigration "com.group:database-project:1.0" // Jar file containing your migration scripts
}

flyway {
    configurations = ["flywayMigration"]
    locations = ["classpath:db/migrations"]
}

Unless I misunderstand your requirements, you don't need a third party project for applying the migrations. (Though you still can if you want, of cause.) In my project, we are in a similar situation, and we have all our Spring Boot applications bundle the migrations scripts with them, and then on start-up we problematically apply the migrations to the database. In this scenario, on a clean database, the first application will perform all migrations, and all subsequent ones will just verify that everything is OK. Flyway supports parallel migrations as well, so there should not be any concurrency issues. You can achieve a similar thing using applying the Flyway plugin to all Boot projects and then make a task dependency from bootRun to flywayMigrate.

Upvotes: 1

Related Questions