Upgrade to Flyway 10.10

Closes gh-40022
This commit is contained in:
Andy Wilkinson 2024-03-19 12:24:47 +00:00
parent e3f8c34b9b
commit a65e1018f0
10 changed files with 59 additions and 255 deletions

View File

@ -95,6 +95,7 @@ dependencies {
exclude group: "commons-logging", module: "commons-logging"
}
optional("org.flywaydb:flyway-core")
optional("org.flywaydb:flyway-database-postgresql")
optional("org.flywaydb:flyway-database-oracle")
optional("org.flywaydb:flyway-sqlserver")
optional("org.freemarker:freemarker")
@ -250,6 +251,7 @@ dependencies {
testImplementation("org.yaml:snakeyaml")
testRuntimeOnly("jakarta.management.j2ee:jakarta.management.j2ee-api")
testRuntimeOnly("org.flywaydb:flyway-database-hsqldb")
testRuntimeOnly("org.jetbrains.kotlin:kotlin-reflect")
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,8 +35,8 @@ import org.flywaydb.core.api.callback.Callback;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.flywaydb.core.api.migration.JavaMigration;
import org.flywaydb.core.extensibility.ConfigurationExtension;
import org.flywaydb.core.internal.database.postgresql.PostgreSQLConfigurationExtension;
import org.flywaydb.database.oracle.OracleConfigurationExtension;
import org.flywaydb.database.postgresql.PostgreSQLConfigurationExtension;
import org.flywaydb.database.sqlserver.SQLServerConfigurationExtension;
import org.springframework.aot.hint.RuntimeHints;
@ -157,7 +157,7 @@ public class FlywayAutoConfiguration {
}
@Bean
@ConditionalOnClass(name = "org.flywaydb.core.internal.database.postgresql.PostgreSQLConfigurationExtension")
@ConditionalOnClass(name = "org.flywaydb.database.postgresql.PostgreSQLConfigurationExtension")
PostgresqlFlywayConfigurationCustomizer postgresqlFlywayConfigurationCustomizer() {
return new PostgresqlFlywayConfigurationCustomizer(this.properties);
}
@ -305,11 +305,7 @@ public class FlywayAutoConfiguration {
map.from(properties.getDryRunOutput()).to((dryRunOutput) -> configuration.dryRunOutput(dryRunOutput));
map.from(properties.getErrorOverrides())
.to((errorOverrides) -> configuration.errorOverrides(errorOverrides));
map.from(properties.getLicenseKey()).to((licenseKey) -> configuration.licenseKey(licenseKey));
map.from(properties.getStream()).to((stream) -> configuration.stream(stream));
map.from(properties.getUndoSqlMigrationPrefix())
.to((undoSqlMigrationPrefix) -> configuration.undoSqlMigrationPrefix(undoSqlMigrationPrefix));
map.from(properties.getCherryPick()).to((cherryPick) -> configuration.cherryPick(cherryPick));
map.from(properties.getJdbcProperties())
.whenNot(Map::isEmpty)
.to((jdbcProperties) -> configuration.jdbcProperties(jdbcProperties));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -291,27 +291,11 @@ public class FlywayProperties {
*/
private String[] errorOverrides;
/**
* Licence key for Flyway Teams.
*/
private String licenseKey;
/**
* Whether to stream SQL migrations when executing them. Requires Flyway Teams.
*/
private Boolean stream;
/**
* File name prefix for undo SQL migrations. Requires Flyway Teams.
*/
private String undoSqlMigrationPrefix;
/**
* Migrations that Flyway should consider when migrating or undoing. When empty all
* available migrations are considered. Requires Flyway Teams.
*/
private String[] cherryPick;
/**
* Properties to pass to the JDBC driver. Requires Flyway Teams.
*/
@ -728,14 +712,6 @@ public class FlywayProperties {
this.errorOverrides = errorOverrides;
}
public String getLicenseKey() {
return this.licenseKey;
}
public void setLicenseKey(String licenseKey) {
this.licenseKey = licenseKey;
}
@DeprecatedConfigurationProperty(replacement = "spring.flyway.oracle.sqlplus", since = "3.2.0")
@Deprecated(since = "3.2.0", forRemoval = true)
public Boolean getOracleSqlplus() {
@ -777,22 +753,6 @@ public class FlywayProperties {
this.stream = stream;
}
public String getUndoSqlMigrationPrefix() {
return this.undoSqlMigrationPrefix;
}
public void setUndoSqlMigrationPrefix(String undoSqlMigrationPrefix) {
this.undoSqlMigrationPrefix = undoSqlMigrationPrefix;
}
public String[] getCherryPick() {
return this.cherryPick;
}
public void setCherryPick(String[] cherryPick) {
this.cherryPick = cherryPick;
}
public Map<String, String> getJdbcProperties() {
return this.jdbcProperties;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,10 +35,8 @@ class NativeImageResourceProviderCustomizer extends ResourceProviderCustomizer {
@Override
public void customize(FluentConfiguration configuration) {
if (configuration.getResourceProvider() == null) {
Scanner<JavaMigration> scanner = new Scanner<>(JavaMigration.class,
Arrays.asList(configuration.getLocations()), configuration.getClassLoader(),
configuration.getEncoding(), configuration.isDetectEncoding(), false, new ResourceNameCache(),
new LocationScannerCache(), configuration.isFailOnMissingLocations());
Scanner<JavaMigration> scanner = new Scanner<>(JavaMigration.class, false, new ResourceNameCache(),
new LocationScannerCache(), configuration);
NativeImageResourceProvider resourceProvider = new NativeImageResourceProvider(scanner,
configuration.getClassLoader(), Arrays.asList(configuration.getLocations()),
configuration.getEncoding(), configuration.isFailOnMissingLocations());

View File

@ -1,57 +0,0 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.flyway;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.Location;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link FlywayAutoConfiguration} with Flyway 10.x.
*
* @author Andy Wilkinson
*/
@ClassPathExclusions({ "flyway-core-*.jar", "flyway-sqlserver-*.jar" })
@ClassPathOverrides({ "org.flywaydb:flyway-core:10.0.0", "com.h2database:h2:2.1.210" })
@EnabledForJreRange(min = JRE.JAVA_17)
class Flyway10xAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true");
@Test
void defaultFlyway() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getLocations())
.containsExactly(new Location("classpath:db/migration"));
});
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.flyway;
import java.util.UUID;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.Location;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link FlywayAutoConfiguration} with Flyway 9.0.x.
*
* @author Andy Wilkinson
*/
@ClassPathExclusions("flyway-*.jar")
@ClassPathOverrides("org.flywaydb:flyway-core:9.0.4")
class Flyway90AutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.withPropertyValues("spring.datasource.url:jdbc:hsqldb:mem:" + UUID.randomUUID());
@Test
void flywayCanBeAutoConfigured() {
this.contextRunner.withUserConfiguration(DataSourceAutoConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getLocations())
.containsExactly(new Location("classpath:db/migration"));
});
}
}

View File

@ -1,54 +0,0 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.flyway;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.Location;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link FlywayAutoConfiguration} with Flyway 9.19.
*
* @author Andy Wilkinson
*/
@ClassPathExclusions("flyway-*.jar")
@ClassPathOverrides("org.flywaydb:flyway-core:9.19.4")
class Flyway91AutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true");
@Test
void defaultFlyway() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getLocations())
.containsExactly(new Location("classpath:db/migration"));
});
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -33,9 +33,9 @@ import org.flywaydb.core.api.callback.Context;
import org.flywaydb.core.api.callback.Event;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.flywaydb.core.api.migration.JavaMigration;
import org.flywaydb.core.internal.database.postgresql.PostgreSQLConfigurationExtension;
import org.flywaydb.core.internal.license.FlywayTeamsUpgradeRequiredException;
import org.flywaydb.core.internal.license.FlywayEditionUpgradeRequiredException;
import org.flywaydb.database.oracle.OracleConfigurationExtension;
import org.flywaydb.database.postgresql.PostgreSQLConfigurationExtension;
import org.flywaydb.database.sqlserver.SQLServerConfigurationExtension;
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
import org.jooq.DSLContext;
@ -66,7 +66,6 @@ import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -584,7 +583,10 @@ class FlywayAutoConfigurationTests {
void batchIsCorrectlyMapped() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.batch=true")
.run(validateFlywayTeamsPropertyOnly("batch"));
.run((context) -> {
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getModernConfig().getFlyway().getBatch()).isTrue();
});
}
@Test
@ -601,14 +603,6 @@ class FlywayAutoConfigurationTests {
.run(validateFlywayTeamsPropertyOnly("errorOverrides"));
}
@Test
void licenseKeyIsCorrectlyMapped(CapturedOutput output) {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.license-key=<<secret>>")
.run((context) -> assertThat(output).contains("License key detected - in order to use Teams or "
+ "Enterprise features, download Flyway Teams Edition & Flyway Enterprise Edition"));
}
@Test
void oracleExtensionIsNotLoadedByDefault() {
FluentConfiguration configuration = mock(FluentConfiguration.class);
@ -714,14 +708,10 @@ class FlywayAutoConfigurationTests {
void streamIsCorrectlyMapped() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.stream=true")
.run(validateFlywayTeamsPropertyOnly("stream"));
}
@Test
void undoSqlMigrationPrefix() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.undo-sql-migration-prefix=undo")
.run(validateFlywayTeamsPropertyOnly("undoSqlMigrationPrefix"));
.run((context) -> {
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getModernConfig().getFlyway().getStream()).isTrue();
});
}
@Test
@ -756,18 +746,17 @@ class FlywayAutoConfigurationTests {
});
}
@Test
void cherryPickIsCorrectlyMapped() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.cherry-pick=1.1")
.run(validateFlywayTeamsPropertyOnly("cherryPick"));
}
@Test
void jdbcPropertiesAreCorrectlyMapped() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.jdbc-properties.prop=value")
.run(validateFlywayTeamsPropertyOnly("jdbcProperties"));
.run((context) -> {
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration()
.getCachedResolvedEnvironments()
.get(flyway.getConfiguration().getCurrentEnvironmentName())
.getJdbcProperties()).containsEntry("prop", "value");
});
}
@Test
@ -781,7 +770,10 @@ class FlywayAutoConfigurationTests {
void outputQueryResultsIsCorrectlyMapped() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.output-query-results=false")
.run(validateFlywayTeamsPropertyOnly("outputQueryResults"));
.run((context) -> {
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getModernConfig().getFlyway().getOutputQueryResults()).isFalse();
});
}
@Test
@ -840,7 +832,11 @@ class FlywayAutoConfigurationTests {
void skipExecutingMigrationsIsCorrectlyMapped() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("spring.flyway.skip-executing-migrations=true")
.run(validateFlywayTeamsPropertyOnly("skipExecutingMigrations"));
.run((context) -> {
Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getConfiguration().getModernConfig().getFlyway().getSkipExecutingMigrations())
.isTrue();
});
}
@Test
@ -923,7 +919,7 @@ class FlywayAutoConfigurationTests {
return (context) -> {
assertThat(context).hasFailed();
Throwable failure = context.getStartupFailure();
assertThat(failure).hasRootCauseInstanceOf(FlywayTeamsUpgradeRequiredException.class);
assertThat(failure).hasRootCauseInstanceOf(FlywayEditionUpgradeRequiredException.class);
assertThat(failure).hasMessageContaining(String.format(" %s ", propertyName));
};
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -121,7 +121,9 @@ class FlywayPropertiesTests {
"javaMigrationClassProvider", "pluginRegister", "resourceProvider", "resolvers");
// Properties we don't want to expose
ignoreProperties(configuration, "resolversAsClassNames", "callbacksAsClassNames", "driver", "modernConfig",
"currentResolvedEnvironment", "reportFilename", "reportEnabled", "workingDirectory");
"currentResolvedEnvironment", "reportFilename", "reportEnabled", "workingDirectory",
"cachedDataSources", "cachedResolvedEnvironments", "currentEnvironmentName", "allEnvironments",
"environmentProvisionMode");
// Handled by the conversion service
ignoreProperties(configuration, "baselineVersionAsString", "encodingAsString", "locationsAsStrings",
"targetAsString");
@ -136,6 +138,8 @@ class FlywayPropertiesTests {
ignoreProperties(configuration, "databaseType", "password", "url", "user");
// Properties not exposed by Flyway
ignoreProperties(configuration, "failOnMissingTarget");
// Properties managed by a proprietary extension
ignoreProperties(configuration, "cherryPick");
List<String> configurationKeys = new ArrayList<>(configuration.keySet());
Collections.sort(configurationKeys);
List<String> propertiesKeys = new ArrayList<>(properties.keySet());

View File

@ -378,13 +378,28 @@ bom {
releaseNotes("https://www.elastic.co/guide/en/elasticsearch/reference/current/release-notes-{version}.html")
}
}
library("Flyway", "9.22.3") {
library("Flyway", "10.10.0") {
group("org.flywaydb") {
modules = [
"flyway-commandline",
"flyway-community-db-support",
"flyway-core",
"flyway-database-db2",
"flyway-database-derby",
"flyway-database-hsqldb",
"flyway-database-informix",
"flyway-database-mongodb",
"flyway-database-oracle",
"flyway-database-postgresql",
"flyway-database-redshift",
"flyway-database-saphana",
"flyway-database-snowflake",
"flyway-database-sybasease",
"flyway-firebird",
"flyway-gcp-bigquery",
"flyway-gcp-spanner",
"flyway-mysql",
"flyway-singlestore",
"flyway-sqlserver"
]
plugins = [