New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for sbt? #527
Comments
Hey. Thanks for your kind comment. I’m happy to look into that. In the end, it shouldn’t be too hard to call the core api from Scala and sbt. It’s just not my main expertise. Here’s how I do this for Maven Line 117 in 902b782
and as an example the migrate mojo Line 41 in 902b782
if you could point me to some resources where I can learn about
Would be a good start |
Hi Michael. Thanks for your quick response. The sbt docs related to building plugins for it appear to begin here: https://www.scala-sbt.org/1.x/docs/Best-Practices.html I'll explore what it takes to do such a thing as well. Thanks again! |
I’ve some code working in principle but it seems that sbt (or Scala) has some issues with Java service loader API that migrations uses internally. As in: no services are discovered. See those. They work just fine in Spring, Quarkus, CLI , Maven and native image. I don’t have the right Google foo in Scala terms to find what’s needed to make them work. Do you? The rest is afaik mainly boiler plate and translating into sbt. |
I have something working now… It would be most awesome if we can work together on this as a starting point. Given organization := "eu.michael-simons.neo4j"
name := "sbt-neo4j-migrate"
version := "0.1"
sbtPlugin := true
scalaVersion := "2.12.16"
javacOptions ++= Seq("--release", "8")
libraryDependencies += "eu.michael-simons.neo4j" % "neo4j-migrations" % "1.7.1" plus package sbthello
import ac.simons.neo4j.migrations.core.{Migrations, MigrationsConfig}
import org.neo4j.driver.*
import sbt.*
import sbt.Keys.*
import sbt.internal.inc.classpath.ClasspathUtil
import java.util.logging.Level
object HelloPlugin extends AutoPlugin {
override def trigger = allRequirements
override def requires = sbt.plugins.SbtPlugin
object autoImport {
val neo4jAddress = settingKey[String]("The jdbc url to use to connect to the database.")
val neo4jUser = settingKey[String]("The user to use to connect to the database.")
val neo4jPassword = settingKey[String]("The password to use to connect to the database.")
val neo4jLocations = settingKey[String]("Locations on the classpath to scan recursively for migrations. Locations may contain both sql and code-based migrations. (default: classpath:neo4j/migrations)")
val neo4jInfo = taskKey[Unit]("Retrieves the complete information about the migrations including applied, pending and current migrations with details and status.")
}
import autoImport.*
override lazy val projectSettings: Seq[Setting[_]] = Seq(
neo4jInfo := {
val address = neo4jAddress.value
val user = neo4jUser.value
val password = neo4jPassword.value
val config = MigrationsConfig.builder()
.withLocationsToScan(neo4jLocations.value)
.build()
val migrations = withContextClassLoader((Compile / externalDependencyClasspath).value)(new Migrations(config, openConnection(address, user, password)))
val s = streams.value
s.log.info(migrations.info().prettyPrint())
}
)
private def openConnection(address: String, user: String, password: String): Driver = {
GraphDatabase
.driver(
address,
AuthTokens.basic(user, password), createDriverConfig
)
}
private def createDriverConfig = Config.builder
.withLogging(Logging.console(Level.SEVERE))
.withUserAgent(Migrations.getUserAgent)
.build
private def withContextClassLoader[T](cp: Types.Id[Keys.Classpath])(f: => T): T = {
val classloader = ClasspathUtil.toLoader(cp.map(_.data), getClass.getClassLoader)
val thread = Thread.currentThread
val oldLoader = thread.getContextClassLoader
try {
thread.setContextClassLoader(classloader)
f
} finally {
thread.setContextClassLoader(oldLoader)
}
}
} I can have a 2nd project looking like this name := "untitled4"
version := "0.1"
neo4jAddress := "bolt://localhost:7687"
neo4jUser := "neo4j"
neo4jPassword := "secret"
neo4jLocations := {
val path = (Compile / packageBin / classDirectory).value
new File(path, "/neo4j/migrations/").toURI.toString
}
enablePlugins(sbthello.HelloPlugin) that will spit out
Wdyt @jec is that something we can start with? |
@michael-simons this looks great! Very quick response, unlike mine. I would like to work with you on this as time allows. This involves a side project of mine, so it wouldn't be during my office hours (east coast USA). What do you see as the next steps? |
So, I would like to discuss deployment first: I have no clue how to deploy such thing :) Maven doesn't seem to be an option. That would need some scripting to sync versions and something that triggers sbt release from within maven during maven release. I could do the latter, but need help to understand sbt release. |
I'm using the Neo4j Java lib in a Scala app, and Neo4j-Migrations looks like a really useful way to maintain constraints and such. However, my workflow is entirely in sbt, and I wonder how I might get this lib to work with that. Does anyone have any insight into that? Is anyone aware of a blog post somewhere that describes it?
Cheers!
The text was updated successfully, but these errors were encountered: