Skip to content

Commit

Permalink
Merge pull request quarkusio#27744 from rmanibus/flyway_baseline_at_s…
Browse files Browse the repository at this point in the history
…tart

Add a config option to enable Flyway baseline feature
  • Loading branch information
gastaldi authored Sep 3, 2023
2 parents b82b03a + 89cb68d commit e3424be
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.quarkus.flyway.test;

import static org.junit.jupiter.api.Assertions.assertNull;

import jakarta.inject.Inject;

import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.MigrationInfo;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class FlywayExtensionBaselineAtStartExistingSchemaHistoryTableTest {
@Inject
Flyway flyway;

static final FlywayH2TestCustomizer customizer = FlywayH2TestCustomizer
.withDbName("quarkus-baseline-at-start-existing-schema-history")
.withPort(11309)
.withInitSqlFile("src/test/resources/h2-init-schema-history-table.sql");

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setBeforeAllCustomizer(customizer::startH2)
.setAfterAllCustomizer(customizer::stopH2)
.withApplicationRoot((jar) -> jar
.addClass(FlywayH2TestCustomizer.class)
.addAsResource("db/migration/V1.0.0__Quarkus.sql")
.addAsResource("baseline-at-start-existing-schema-history-table-config.properties",
"application.properties"));

@Test
@DisplayName("Baseline at start is not executed against existing schema-history-table")
public void testFlywayConfigInjection() {
MigrationInfo migrationInfo = flyway.info().current();
assertNull(migrationInfo, "Flyway baseline was executed on existing schema history table");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.quarkus.flyway.test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import jakarta.inject.Inject;

import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.MigrationInfo;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class FlywayExtensionBaselineAtStartTest {
@Inject
Flyway flyway;

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addAsResource("db/migration/V1.0.0__Quarkus.sql")
.addAsResource("baseline-at-start-config.properties", "application.properties"));

@Test
@DisplayName("Baseline at start is executed against empty schema")
public void testFlywayConfigInjection() {
MigrationInfo migrationInfo = flyway.info().current();
assertNotNull(migrationInfo, "No Flyway migration was executed");
assertTrue(migrationInfo.getType().isBaseline(), "Flyway migration is not a baseline");
String currentVersion = migrationInfo
.getVersion()
.toString();

assertEquals("1.0.1", currentVersion);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
quarkus.datasource.db-kind=h2
quarkus.datasource.username=sa
quarkus.datasource.password=sa
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:quarkus-baseline-at-start;DB_CLOSE_DELAY=-1

# Flyway config properties
quarkus.flyway.baseline-at-start=true
quarkus.flyway.baseline-version=1.0.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
quarkus.datasource.db-kind=h2
quarkus.datasource.username=sa
quarkus.datasource.password=sa
quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost:11309/mem:quarkus-baseline-at-start-existing-schema-history;DB_CLOSE_DELAY=-1

# Flyway config properties
quarkus.flyway.baseline-at-start=true
quarkus.flyway.baseline-version=1.0.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE TABLE "flyway_schema_history" (
"installed_rank" integer NOT NULL,
"version" character varying(50),
"description" character varying(200) NOT NULL,
"type" character varying(20) NOT NULL,
"script" character varying(1000) NOT NULL,
"checksum" integer,
"installed_by" character varying(100) NOT NULL,
"installed_on" timestamp without time zone DEFAULT now() NOT NULL,
"execution_time" integer NOT NULL,
"success" boolean NOT NULL,
CONSTRAINT flyway_schema_history_pk PRIMARY KEY ("installed_rank")
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
public class FlywayContainer {

private final Flyway flyway;

private final boolean baselineAtStart;
private final boolean cleanAtStart;
private final boolean migrateAtStart;
private final boolean repairAtStart;
Expand All @@ -15,10 +17,11 @@ public class FlywayContainer {
private final boolean createPossible;
private final String id;

public FlywayContainer(Flyway flyway, boolean cleanAtStart, boolean migrateAtStart, boolean repairAtStart,
boolean validateAtStart,
public FlywayContainer(Flyway flyway, boolean baselineAtStart, boolean cleanAtStart, boolean migrateAtStart,
boolean repairAtStart, boolean validateAtStart,
String dataSourceName, boolean hasMigrations, boolean createPossible) {
this.flyway = flyway;
this.baselineAtStart = baselineAtStart;
this.cleanAtStart = cleanAtStart;
this.migrateAtStart = migrateAtStart;
this.repairAtStart = repairAtStart;
Expand All @@ -33,6 +36,10 @@ public Flyway getFlyway() {
return flyway;
}

public boolean isBaselineAtStart() {
return baselineAtStart;
}

public boolean isCleanAtStart() {
return cleanAtStart;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public FlywayContainer createFlyway(DataSource dataSource, String dataSourceName
final Flyway flyway = new FlywayCreator(matchingRuntimeConfig, matchingBuildTimeConfig, matchingConfigCustomizers(
configCustomizerInstances, dataSourceName)).withCallbacks(callbacks)
.createFlyway(dataSource);
return new FlywayContainer(flyway, matchingRuntimeConfig.cleanAtStart, matchingRuntimeConfig.migrateAtStart,
return new FlywayContainer(flyway, matchingRuntimeConfig.baselineAtStart, matchingRuntimeConfig.cleanAtStart,
matchingRuntimeConfig.migrateAtStart,
matchingRuntimeConfig.repairAtStart, matchingRuntimeConfig.validateAtStart,
dataSourceName, hasMigrations,
createPossible);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,22 @@ public static FlywayDataSourceRuntimeConfig defaultConfig() {
public boolean validateAtStart;

/**
* Enable the creation of the history table if it does not exist already.
* true to execute Flyway baseline before migrations This flag is ignored if the flyway_schema_history table exists in the
* current schema or if the current schema is empty.
* Note that this will not automatically call migrate, you must either enable baselineAtStart or programmatically call
* flyway.migrate().
*/
@ConfigItem
public boolean baselineOnMigrate;

/**
* true to execute Flyway baseline automatically when the application starts.
* This flag is ignored if the flyway_schema_history table exists in the current schema.
* This will work even if the current schema is empty.
*/
@ConfigItem
public boolean baselineAtStart;

/**
* The initial baseline version.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,16 @@
import jakarta.enterprise.inject.UnsatisfiedResolutionException;

import org.flywaydb.core.Flyway;
import org.flywaydb.core.FlywayExecutor;
import org.flywaydb.core.api.callback.Callback;
import org.flywaydb.core.api.migration.JavaMigration;
import org.flywaydb.core.api.output.BaselineResult;
import org.flywaydb.core.internal.callback.CallbackExecutor;
import org.flywaydb.core.internal.database.base.Database;
import org.flywaydb.core.internal.database.base.Schema;
import org.flywaydb.core.internal.jdbc.StatementInterceptor;
import org.flywaydb.core.internal.resolver.CompositeMigrationResolver;
import org.flywaydb.core.internal.schemahistory.SchemaHistory;
import org.jboss.logging.Logger;

import io.quarkus.agroal.runtime.DataSources;
Expand Down Expand Up @@ -101,6 +109,10 @@ public void doStartActions() {
if (flywayContainer.isValidateAtStart()) {
flywayContainer.getFlyway().validate();
}
if (flywayContainer.isBaselineAtStart()) {
new FlywayExecutor(flywayContainer.getFlyway().getConfiguration())
.execute(new BaselineCommand(flywayContainer.getFlyway()), true, null);
}
if (flywayContainer.isRepairAtStart()) {
flywayContainer.getFlyway().repair();
}
Expand All @@ -109,4 +121,21 @@ public void doStartActions() {
}
}
}

static class BaselineCommand implements FlywayExecutor.Command<BaselineResult> {
BaselineCommand(Flyway flyway) {
this.flyway = flyway;
}

final Flyway flyway;

@Override
public BaselineResult execute(CompositeMigrationResolver cmr, SchemaHistory schemaHistory, Database d,
Schema defaultSchema, Schema[] s, CallbackExecutor ce, StatementInterceptor si) {
if (!schemaHistory.exists()) {
return flyway.baseline();
}
return null;
}
}
}

0 comments on commit e3424be

Please sign in to comment.