-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add database migrations core * Replace harmonica code with jar. Create DbMigrateTask * Create db/migrate dir. Add PackageName tests * Add db migrate test * jitpack is no longer needed * Nits * New base class + fix test
- Loading branch information
Showing
24 changed files
with
458 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
42 changes: 42 additions & 0 deletions
42
activerecord/src/main/kotlin/kales/migrations/KalesDatabaseConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package kales.migrations | ||
|
||
import org.yaml.snakeyaml.Yaml | ||
import java.io.InputStream | ||
|
||
/** Represents a Kales database config as defined in a database.yml file */ | ||
data class KalesDatabaseConfig( | ||
val environment: String, | ||
val adapter: String, | ||
val host: String, | ||
val database: String, | ||
val username: String, | ||
val password: String | ||
) { | ||
override fun toString(): String { | ||
return if (adapter == "h2") { | ||
"jdbc:$adapter:$host:$database" | ||
} else { | ||
"jdbc:$adapter://$host/$database?user=$username&password=$password" | ||
} | ||
} | ||
|
||
companion object { | ||
@Suppress("UNCHECKED_CAST") | ||
fun fromDatabaseYml(fileStream: InputStream): KalesDatabaseConfig { | ||
val yaml = Yaml() | ||
val data = yaml.load<Map<String, Any>>(fileStream) | ||
// TODO handle muliple environments | ||
val devData = data["development"] as? Map<String, String> ?: throwMissingField("development") | ||
val adapter = devData["adapter"] ?: throwMissingField("adapter") | ||
val host = devData["host"] ?: throwMissingField("host") | ||
val database = devData["database"] ?: throwMissingField("database") | ||
val username = devData["username"] ?: "" | ||
val password = devData["password"] ?: "" | ||
return KalesDatabaseConfig("development", adapter, host, database, username, password) | ||
} | ||
|
||
private fun throwMissingField(name: String): Nothing = | ||
throw IllegalArgumentException( | ||
"Please set a value for the field '$name' in the file database.yml") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package kales.migrations | ||
|
||
import com.improve_future.harmonica.core.AbstractMigration | ||
|
||
abstract class Migration : AbstractMigration() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ ext { | |
truthVersion = '0.42' | ||
ktorVersion = '1.1.2' | ||
jdbiVersion = '3.6.0' | ||
h2DBVersion = '1.4.197' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package kales.cli | ||
|
||
import com.improve_future.harmonica.core.AbstractMigration | ||
import com.improve_future.harmonica.core.Connection | ||
import com.improve_future.harmonica.service.VersionService | ||
import org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory | ||
import java.io.File | ||
|
||
internal class HarmonicaUp( | ||
private val migrationsDirectory: File, | ||
private val connection: Connection | ||
) { | ||
private val versionService = VersionService("schema_migrations") | ||
|
||
fun run() { | ||
connection.use { connection -> | ||
connection.transaction { | ||
versionService.setupHarmonicaMigrationTable(connection) | ||
} | ||
for (file in migrationsDirectory.listFiles().sortedBy { it.name }) { | ||
val migrationVersion = file.name.split('_').first() | ||
if (versionService.isVersionMigrated(connection, migrationVersion)) { | ||
continue | ||
} | ||
connection.transaction { | ||
val migration = readMigration(file.readText()) | ||
migration.connection = connection | ||
migration.up() | ||
versionService.saveVersion(connection, migrationVersion) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun readMigration(script: String) = | ||
engine.eval(removePackageStatement(script)) as AbstractMigration | ||
|
||
private companion object { | ||
val engine by lazy { | ||
KotlinJsr223JvmLocalScriptEngineFactory().scriptEngine | ||
} | ||
|
||
private fun removePackageStatement(script: String) = | ||
script.replace(Regex("^\\s*package\\s+.+"), "") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package kales.cli | ||
|
||
/** Represents a Java package, g.: com.foo.bar */ | ||
internal class PackageName private constructor(private val stringRepresentation: String) { | ||
private val parts = stringRepresentation.split(".") | ||
|
||
/** Returns a new [PackageName] representing the parent package */ | ||
val parentPackage by lazy { | ||
if (parts.size > 1) { | ||
PackageName(parts.slice(0..parts.size - 2).joinToString(".")) | ||
} else { | ||
throw IllegalStateException("Unable to obtain parent package of '$this'") | ||
} | ||
} | ||
|
||
fun isValid() = stringRepresentation.matches(VALID_PKG_REGEX.toRegex()) | ||
|
||
fun childPackage(vararg parts: String) = | ||
PackageName("$stringRepresentation.${parts.joinToString(".")}") | ||
|
||
override fun toString() = stringRepresentation | ||
|
||
override fun equals(other: Any?): Boolean { | ||
if (this === other) return true | ||
if (javaClass != other?.javaClass) return false | ||
|
||
other as PackageName | ||
|
||
if (stringRepresentation != other.stringRepresentation) return false | ||
|
||
return true | ||
} | ||
|
||
override fun hashCode(): Int { | ||
return stringRepresentation.hashCode() | ||
} | ||
|
||
companion object { | ||
private val VALID_PKG_REGEX = "^(?:\\w+|\\w+\\.\\w+)+\$".toPattern() | ||
|
||
/** Parses the provided [stringRepresentation] into a [PackageName] or throws if invalid */ | ||
fun parse(stringRepresentation: String): PackageName { | ||
val pkg = PackageName(stringRepresentation) | ||
return if (!pkg.isValid()) { | ||
throw IllegalArgumentException("Invalid package name $stringRepresentation") | ||
} else { | ||
pkg | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package kales.cli.task | ||
|
||
import com.github.ajalt.clikt.core.UsageError | ||
import com.improve_future.harmonica.core.Connection | ||
import com.improve_future.harmonica.core.DbConfig | ||
import com.improve_future.harmonica.core.Dbms | ||
import kales.cli.HarmonicaUp | ||
import kales.cli.relativePathFor | ||
import kales.migrations.KalesDatabaseConfig | ||
import java.io.File | ||
|
||
class DbMigrateTask(workingDirectory: File) : KalesContextualTask(workingDirectory) { | ||
override fun run() { | ||
val databaseYml = File(resourcesDir, "database.yml") | ||
if (!databaseYml.exists()) { | ||
throw UsageError("database.yml file not found.\n" + | ||
"Plase make sure it exists under src/main/resources and try again") | ||
} | ||
val kalesDbConfig = KalesDatabaseConfig.fromDatabaseYml(databaseYml.inputStream()) | ||
val harmonicaDbConfig = DbConfig { | ||
dbName = kalesDbConfig.database | ||
user = kalesDbConfig.username | ||
password = kalesDbConfig.password | ||
host = kalesDbConfig.password | ||
dbms = when (kalesDbConfig.adapter) { | ||
"postgresql" -> Dbms.PostgreSQL | ||
"mysql" -> Dbms.MySQL | ||
"sqlite" -> Dbms.SQLite | ||
"oracle" -> Dbms.Oracle | ||
"sqlserver" -> Dbms.SQLServer | ||
"h2" -> Dbms.H2 | ||
else -> throw IllegalArgumentException("Unknown database adapter ${kalesDbConfig.adapter}") | ||
} | ||
} | ||
val dbMigrateDir = File(appDirectory.parentFile, relativePathFor("db", "migrate")) | ||
val connection = Connection(harmonicaDbConfig) | ||
val harmonicaUp = HarmonicaUp(dbMigrateDir, connection) | ||
harmonicaUp.run() | ||
} | ||
} |
Oops, something went wrong.