Recently I wanted to use Flyway to manage my database migrations for a Play 2.4 application using slick 3.x. Unfortunately as this stack is quite new, the play-flyway plugin no longer works with Play 2.4.

Fortunately there is a module called flyway-play which integrates Flyway into Play 2.4. Unfortunately there is no Slick 3.x support at present. But the good news is that there is a PR that adds support for Slick 3.x. The bad news is that this PR has been languishing unmerged since September 15 2015. So if you are desperately in need of this support, you might want to go ahead and patch it yourself locally and be done with it until it is merged.

Another alternative is to use the Flyway sbt plugin to manage your migrations. It needs a few tweaks to get it to work with Slick 3.x so that you can reuse configurations from your application.conf file.

These steps are for sbt version 0.13.8. You may need to tweak them if you are using another version of SBT

Here are the steps required to get this working.

  1. Add the Flyway resolver and plugin to your project/plugins.sbt file:
resolvers += "Flyway" at "http://flywaydb.org/repo"

addSbtPlugin("org.flywaydb" % "flyway-sbt" % "3.2.1")
  1. Create a flyway.sbt file in your project root to link up your application.conf database settings with Flyway:
import sbt._
import com.typesafe.config.ConfigFactory

lazy val flywayDBName = "YOUR_DB_NAME"

lazy val flywayDbConf = settingKey[(String, String, String)]("Typesafe config file with slick settings")

flywayDbConf := {
    val cfg = ConfigFactory.parseFile((resourceDirectory in Compile).value / "application.conf")
    val prefix = s"slick.dbs.${flywayDBName}.db"
    (cfg.getString(s"$prefix.url"), cfg.getString(s"$prefix.user"), cfg.getString(s"$prefix.password"))
}

flywaySettings

flywayUrl := flywayDbConf.value._1
flywayUser := flywayDbConf.value._2
flywayPassword := flywayDbConf.value._3

And basically you are done! :) You should be able to run flywayMigrate in SBT and have it use all the Slick settings you’ve defined in your conf/application.conf file:

flywayMigrate

What about if you want to automatically run migrations when you run up your Play application?

  1. I’ve create a task that displays the existing Flyway migration status and prompts you whether to run a migration. If you choose ‘y’ it then runs any pending migrations and starts the Play application. To do this update your build.sbt file with:
lazy val migrate = taskKey[Unit]("Migrate DB with Flyway")
migrate := Def.taskDyn {
  flywayInfo.value
  println("do you want to migrate the schema? y/n")
  val confirm = readLine()
  if (confirm == "y") {
    Def.task {
      flywayMigrate.value
      flywayInfo.value
    }
  } else {
    Def.task { println("-- skipping migration --") }
  }
}.value

addCommandAlias("runM", ";migrate;run")

Now you can run migrations and then start your Play application through SBT with:

runM

Running migrations

Skipping migrations