Skip to content

Commit

Permalink
#86 Added liquibase migrations at startup
Browse files Browse the repository at this point in the history
  • Loading branch information
vityaman committed Apr 25, 2024
1 parent 9787f16 commit f5cde92
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.vityaman.lms.botalka.app.spring.storage

import org.springframework.beans.factory.annotation.Value
import org.springframework.jdbc.datasource.SingleConnectionDataSource
import org.springframework.stereotype.Component
import ru.vityaman.lms.botalka.storage.migration.LiquibaseMigration
import kotlin.io.path.Path

@Component
class SpringMigration(
@Value("\${spring.liquibase.change-log}")
changelog: String,

@Value("\${spring.datasource.url}")
url: String,

@Value("\${spring.datasource.username}")
username: String,

@Value("\${spring.datasource.password}")
password: String,
) {
init {
val suppressClose = false
SingleConnectionDataSource(url, username, password, suppressClose)
.use { LiquibaseMigration(Path(changelog), it).start() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.vityaman.lms.botalka.storage.migration

import liquibase.Liquibase
import liquibase.database.DatabaseFactory
import liquibase.database.jvm.JdbcConnection
import liquibase.resource.ClassLoaderResourceAccessor
import java.nio.file.Path
import javax.sql.DataSource
import kotlin.io.path.pathString

class LiquibaseMigration(
private val changelog: Path,
private val source: DataSource,
) {
@Suppress("Deprecation")
fun start() {
val resources = ClassLoaderResourceAccessor(javaClass.classLoader)
println("Migration::start")
source.connection.use { connection ->
val database = DatabaseFactory.getInstance()
.findCorrectDatabaseImplementation(JdbcConnection(connection))
Liquibase(changelog.pathString, resources, database).use {
it.update("development")
}
}
println("Migration::end")
}
}
6 changes: 6 additions & 0 deletions botalka/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ spring:
url: r2dbc:postgresql://database:5432/postgres
username: postgres
password: postgres
datasource:
url: jdbc:postgresql://database:5432/postgres
username: postgres
password: postgres
liquibase:
change-log: database/changelog.sql
server:
port: 8080
springdoc:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
--liquibase formatted sql

--changeset vityaman:init
CREATE SCHEMA lms;

--changeset vityaman:users
CREATE DOMAIN lms.alias AS VARCHAR(32)
CHECK (VALUE ~ '[a-zA-Z]{3,31}');

Expand All @@ -24,6 +28,7 @@ CREATE TYPE lms.role AS ENUM (
'student'
);

--changeset vityaman:promotions
CREATE TYPE lms.promotion_request_status AS ENUM (
'created',
'rejected',
Expand All @@ -40,6 +45,7 @@ CREATE TABLE lms.promotion_request (
UNIQUE (user_id, role)
);

--changeset vityaman:homeworks
CREATE DOMAIN lms.score AS smallint
CHECK (0 < VALUE AND VALUE <= 2000);

Expand All @@ -53,6 +59,7 @@ CREATE TABLE lms.homework (
creation_moment timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP
);

--changeset vityaman:events
CREATE SEQUENCE lms.event_id_seq AS integer START 1;

CREATE TABLE lms.homework_submission (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package ru.vityaman.lms.botalka.app.spring

import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
class BotalkaApplicationTests {
class BotalkaApplicationTests : BotalkaTestSuite() {
@Test
fun contextLoads() {
// Okay
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ContextConfiguration
import ru.vityaman.lms.botalka.app.spring.storage.DatabaseContainerInitializer
import ru.vityaman.lms.botalka.app.spring.storage.SpringMigration
import ru.vityaman.lms.botalka.storage.jooq.Lms.Companion.LMS
import ru.vityaman.lms.botalka.storage.jooq.util.toFlux

Expand All @@ -22,8 +23,12 @@ abstract class BotalkaTestSuite {
@Autowired
private lateinit var database: DSLContext

@Autowired
private lateinit var migration: SpringMigration

@AfterEach
fun afterEach(): Unit = runBlocking {
migration.let { }
for (table in LMS.tables) {
launch {
database
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package ru.vityaman.lms.botalka.app.spring.storage

import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.utility.MountableFile

class DatabaseContainer : AutoCloseable {
private val postgres = PostgreSQLContainer("postgres")
.withCopyToContainer(SCHEMA_SCRIPT, INIT_SQL)

val r2dbcUrl: String
get() {
Expand All @@ -15,6 +13,14 @@ class DatabaseContainer : AutoCloseable {
return "r2dbc:postgresql://$host:$port/$name"
}

val jdbcUrl: String
get() {
val host = postgres.host
val port = postgres.firstMappedPort
val name = postgres.databaseName
return "jdbc:postgresql://$host:$port/$name"
}

val username: String get() = postgres.username

val password: String get() = postgres.password
Expand All @@ -29,11 +35,6 @@ class DatabaseContainer : AutoCloseable {
}

companion object {
private const val INIT_SQL = "/docker-entrypoint-initdb.d/init.sql"

private val SCHEMA_SCRIPT =
MountableFile.forClasspathResource("database/schema.sql")

val instance: DatabaseContainer by lazy { DatabaseContainer() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class DatabaseContainerInitializer :
"spring.r2dbc.url=${database.r2dbcUrl}",
"spring.r2dbc.username=${database.username}",
"spring.r2dbc.password=${database.password}",
"spring.datasource.url=${database.jdbcUrl}",
"spring.datasource.username=${database.username}",
"spring.datasource.password=${database.password}",
).applyTo(ctx.environment)
}
}
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/lms.conventions.jooq.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jooq {
executions {
create("main") {
val jdbcUrl = {
val schemaSql = "$projectDir/src/main/resources/database/schema.sql"
val schemaSql = "$projectDir/src/main/resources/database/changelog.sql"
val protocol = "jdbc:tc:postgresql:16"
val tmpfs = "TC_TMPFS=/testtmpfs:rw&amp"
val script = "TC_INITSCRIPT=file:$schemaSql"
Expand Down
4 changes: 4 additions & 0 deletions buildSrc/src/main/kotlin/lms.conventions.spring.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
runtimeOnly("org.postgresql:r2dbc-postgresql")

implementation("org.liquibase:liquibase-core")
implementation("org.springframework.boot:spring-boot-starter-jdbc")
runtimeOnly("org.postgresql:postgresql")

implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("io.micrometer:micrometer-registry-prometheus")

Expand Down

0 comments on commit f5cde92

Please sign in to comment.