fix: skip reapplying successful Flyway migrations when checksum chang…#97
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughCentralized Flyway bean construction into a private helper and added a new Spring property Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip You can disable poems in the walkthrough.Disable the |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main/java/com/db/piramalswasthya/config/FlywayConfig.java (1)
18-64: Consider extracting a helper method to reduce duplication.The same configuration pattern is repeated across all four Flyway beans—only the
DataSourceand migrationlocationsdiffer. Extracting a helper method would reduce duplication and make future maintenance easier.♻️ Proposed refactor to reduce duplication
`@Configuration` public class FlywayConfig { `@Value`("${amrit.flyway.ignore-applied-migration-checksum:false}") private boolean ignoreAppliedMigrationChecksum; + private Flyway createFlyway(DataSource dataSource, String location) { + FluentConfiguration config = Flyway.configure() + .dataSource(dataSource) + .locations(location) + .baselineOnMigrate(true); + if (ignoreAppliedMigrationChecksum) { + config.ignoreMigrationPatterns("*:applied"); + } + return config.load(); + } + `@Bean` public Flyway flywayDbiemr(`@Qualifier`("dbiemrDataSource") DataSource dataSource) { - FluentConfiguration config = Flyway.configure() - .dataSource(dataSource) - .locations("classpath:db/migration/dbiemr") - .baselineOnMigrate(true); - if (ignoreAppliedMigrationChecksum) { - config.ignoreMigrationPatterns("*:applied"); - } - return config.load(); + return createFlyway(dataSource, "classpath:db/migration/dbiemr"); } `@Bean` public Flyway flywayDbidentity(`@Qualifier`("dbidentityDataSource") DataSource dataSource) { - FluentConfiguration config = Flyway.configure() - .dataSource(dataSource) - .locations("classpath:db/migration/dbidentity") - .baselineOnMigrate(true); - if (ignoreAppliedMigrationChecksum) { - config.ignoreMigrationPatterns("*:applied"); - } - return config.load(); + return createFlyway(dataSource, "classpath:db/migration/dbidentity"); } // ... same for dbreporting and db1097identity }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/db/piramalswasthya/config/FlywayConfig.java` around lines 18 - 64, The four bean methods flywayDbiemr, flywayDbidentity, flywayDbreporting, and flywayDb1097identity duplicate the same FluentConfiguration logic; extract a private helper method (e.g., createFlyway(DataSource dataSource, String location)) that builds Flyway.configure().dataSource(dataSource).locations(location).baselineOnMigrate(true) and applies the ignoreAppliedMigrationChecksum branch (config.ignoreMigrationPatterns("*:applied") when true), then return config.load(); update each bean to call this helper with its DataSource and the appropriate "classpath:db/migration/..." location to remove duplication while preserving behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/com/db/piramalswasthya/config/FlywayConfig.java`:
- Around line 24-26: The pattern "*:applied" passed to
config.ignoreMigrationPatterns is invalid; in FlywayConfig where
ignoreAppliedMigrationChecksum is checked, replace that pattern with a valid
status (for example use "*:ignored" or simply "*" depending on intended scope)
or, if the goal is to bypass checksum validation for already applied migrations,
switch to the appropriate configuration (e.g., disable validation via
config.validateOnMigrate(false) or another Flyway API) instead of using
"applied"; update the call to config.ignoreMigrationPatterns(...) or the
alternative setting accordingly.
---
Nitpick comments:
In `@src/main/java/com/db/piramalswasthya/config/FlywayConfig.java`:
- Around line 18-64: The four bean methods flywayDbiemr, flywayDbidentity,
flywayDbreporting, and flywayDb1097identity duplicate the same
FluentConfiguration logic; extract a private helper method (e.g.,
createFlyway(DataSource dataSource, String location)) that builds
Flyway.configure().dataSource(dataSource).locations(location).baselineOnMigrate(true)
and applies the ignoreAppliedMigrationChecksum branch
(config.ignoreMigrationPatterns("*:applied") when true), then return
config.load(); update each bean to call this helper with its DataSource and the
appropriate "classpath:db/migration/..." location to remove duplication while
preserving behavior.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/environment/common_docker.propertiessrc/main/environment/common_example.propertiessrc/main/java/com/db/piramalswasthya/config/FlywayConfig.javasrc/main/resources/application.properties
| spring.datasource.db1097identity.password=${DATABASE_IDENTITY_PASSWORD} | ||
| spring.datasource.db1097identity.driver-class-name=com.mysql.cj.jdbc.Driver | ||
|
|
||
| amrit.flyway.ignore-applied-migration-checksum=${AMRIT_FLYWAY_IGNORE_APPLIED:false} |
There was a problem hiding this comment.
Already present in application properties. These common_* file changes are not needed.
|
@KadariPavani have you tested this? Can you mention the steps? |
…ionPatterns #117
- Replace invalid `ignoreMigrationPatterns("*:applied")` (Flyway Teams-only)
with `flyway.repair()` which realigns checksums and removes failed entries
- Add `initSql("SET FOREIGN_KEY_CHECKS=0")` to handle FK ordering in migrations
- Reorder migrations: db_identity before db_iemr (cross-database dependency)
- Move repair logic to FlywayMigrator (conditional on flag)
- Revert common_docker.properties and common_example.properties changes
per reviewer feedback (property already in application.properties)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/main/java/com/db/piramalswasthya/config/FlywayConfig.java (1)
16-21: Extract shared Flyway builder logic to avoid 4-way duplication.Lines 16-51 repeat identical configuration structure. A private helper (datasource + location) will reduce drift and make future behavior changes safer.
Also applies to: 26-31, 36-41, 46-51
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/db/piramalswasthya/config/FlywayConfig.java` around lines 16 - 21, Multiple identical Flyway.configure() chains are duplicated; extract a private helper like private FluentConfiguration baseFlywayConfig(DataSource dataSource, String location) that performs Flyway.configure().dataSource(dataSource).locations(location).baselineOnMigrate(true).initSql("SET FOREIGN_KEY_CHECKS=0") and return the FluentConfiguration; then replace each duplicated block (the places that currently call Flyway.configure() ... and then config.load()) to call baseFlywayConfig(dataSource, "classpath:db/migration/dbiemr").load() (or pass the appropriate location) so all callers reuse the same builder logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/com/db/piramalswasthya/config/FlywayConfig.java`:
- Around line 20-21: The FlywayConfig class currently calls initSql("SET
FOREIGN_KEY_CHECKS=0") in each Flyway bean which disables FK checks at the
datasource/session level and can leak into pooled connections; remove the
initSql(...) invocation from all four Flyway bean configurations in FlywayConfig
(i.e., the Flyway bean factory methods) so the Flyway config no longer sets
session-level FK checks, and instead ensure FK disable/enable is handled inside
individual migration scripts; update the Flyway bean methods to return
config.load() (or equivalent) without calling initSql.
In `@src/main/java/com/db/piramalswasthya/config/FlywayMigrator.java`:
- Around line 34-40: The current code in FlywayMigrator calls
flywayDbidentity.repair(), flywayDb1097identity.repair(), flywayDbiemr.repair(),
and flywayDbreporting.repair() whenever ignoreAppliedMigrationChecksum is true,
which unconditionally removes failed migration entries; change this so repair()
is not invoked on every startup—remove the unconditional repair block and
instead perform a validate/migrate attempt (or call flyway.validate()) for each
Flyway instance (flywayDbidentity, flywayDb1097identity, flywayDbiemr,
flywayDbreporting), catch the FlywayValidateException (or inspect flyway.info()
for failed states), and only call the corresponding .repair() when a
checksum/validation error is detected (and then log the exact validation error
before repairing) so failed migrations are not silently discarded.
---
Nitpick comments:
In `@src/main/java/com/db/piramalswasthya/config/FlywayConfig.java`:
- Around line 16-21: Multiple identical Flyway.configure() chains are
duplicated; extract a private helper like private FluentConfiguration
baseFlywayConfig(DataSource dataSource, String location) that performs
Flyway.configure().dataSource(dataSource).locations(location).baselineOnMigrate(true).initSql("SET
FOREIGN_KEY_CHECKS=0") and return the FluentConfiguration; then replace each
duplicated block (the places that currently call Flyway.configure() ... and then
config.load()) to call baseFlywayConfig(dataSource,
"classpath:db/migration/dbiemr").load() (or pass the appropriate location) so
all callers reuse the same builder logic.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main/java/com/db/piramalswasthya/config/FlywayConfig.javasrc/main/java/com/db/piramalswasthya/config/FlywayMigrator.java
src/main/java/com/db/piramalswasthya/config/FlywayMigrator.java
Outdated
Show resolved
Hide resolved
- Remove initSql("SET FOREIGN_KEY_CHECKS=0") to prevent FK-disabled
state leaking into pooled connections (CodeRabbit critical)
- Replace unconditional repair() with try-catch: only repair when
FlywayValidateException is caught and flag is enabled (CodeRabbit major)
- Extract createFlyway() helper to reduce 4-way duplication (CodeRabbit nitpick)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main/java/com/db/piramalswasthya/config/FlywayMigrator.java (1)
39-39: Remove direct stdout print in migrator path.Line 39 uses
System.out.println("SUCCESS")while structured logging already exists at Line 40. Prefer logger-only output.🧹 Suggested cleanup
- System.out.println("SUCCESS"); logger.info("Flyway migration completed successfully");🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/db/piramalswasthya/config/FlywayMigrator.java` at line 39, Remove the direct stdout print in FlywayMigrator by deleting the System.out.println("SUCCESS") call and rely on the existing structured logger (the logger used in FlywayMigrator, just after the print) to emit the success message; ensure no other direct System.out prints remain in the migrate/run method of the FlywayMigrator class and that the logger invocation (e.g., logger.info(...) or similar) provides the success text.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/com/db/piramalswasthya/config/FlywayMigrator.java`:
- Around line 46-52: The catch block in FlywayMigrator currently treats all
FlywayValidateException cases the same when ignoreAppliedMigrationChecksum is
true; change this so we only call flyway.repair() and flyway.migrate() for
checksum-mismatch cases: either (A) inspect the FlywayValidateException message
for checksum-related text before repairing (only proceed if it indicates a
checksum mismatch), or (B) refactor to use flyway.validateWithResult() and
examine the returned ValidateResult.invalidMigrations entries to detect checksum
mismatches explicitly, and only then invoke flyway.repair() / flyway.migrate();
keep the ignoreAppliedMigrationChecksum flag logic and only narrow the trigger
to checksum-only failures.
---
Nitpick comments:
In `@src/main/java/com/db/piramalswasthya/config/FlywayMigrator.java`:
- Line 39: Remove the direct stdout print in FlywayMigrator by deleting the
System.out.println("SUCCESS") call and rely on the existing structured logger
(the logger used in FlywayMigrator, just after the print) to emit the success
message; ensure no other direct System.out prints remain in the migrate/run
method of the FlywayMigrator class and that the logger invocation (e.g.,
logger.info(...) or similar) provides the success text.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main/java/com/db/piramalswasthya/config/FlywayConfig.javasrc/main/java/com/db/piramalswasthya/config/FlywayMigrator.java
| } catch (FlywayValidateException e) { | ||
| if (ignoreAppliedMigrationChecksum) { | ||
| logger.warn("Checksum mismatch detected for {}: {}. Repairing schema history...", | ||
| schemaName, e.getMessage()); | ||
| flyway.repair(); | ||
| flyway.migrate(); | ||
| } else { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n src/main/java/com/db/piramalswasthya/config/FlywayMigrator.javaRepository: PSMRI/AMRIT-DB
Length of output: 2511
🌐 Web query:
Flyway Java API checksum mismatch detection FlywayValidateException Spring Boot 3
💡 Result:
Detect checksum mismatches via Java API (Spring Boot 3)
Spring Boot auto-runs Flyway migrate() on startup; migrate() runs validation first, and a checksum mismatch will surface as FlywayValidateException. To detect/report it yourself (without relying on the thrown exception message), call validateWithResult() and inspect the returned ValidateResult. Flyway validation compares the checksum stored in flyway_schema_history with the checksum computed from the migration on your classpath (CRC32 for SQL). [1][2][3]
Example (recommended): custom FlywayMigrationStrategy
Register a bean to validate first, then decide what to do (fail fast, log details, or conditionally repair() only in dev).
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.output.ValidateOutput;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.context.annotation.Bean;
`@Bean`
FlywayMigrationStrategy flywayMigrationStrategy() {
return (Flyway flyway) -> {
var result = flyway.validateWithResult(); // does NOT throw; returns details [2]
if (!result.validationSuccessful) {
for (ValidateOutput m : result.invalidMigrations) {
// m.description / m.version / m.filepath etc. (fields depend on Flyway version)
System.err.println("Flyway invalid migration: " + m);
}
throw new IllegalStateException("Flyway validation failed; see invalidMigrations.");
}
flyway.migrate();
};
}Spring Boot provides FlywayMigrationStrategy specifically to override the default migration behavior. [4]
Why the checksum mismatch happens
Flyway validation fails if it detects differences in checksums (and/or names/types) between applied and locally resolved migrations. Common causes include: editing an already-applied migration, line-ending/encoding changes, placeholder/config differences, or (more rarely) checksum calculation behavior changes across Flyway versions. [1][3]
What to do when you detect a mismatch
- Best practice (prod/shared DB): do not modify applied versioned migrations; create a new migration to correct/adjust schema.
- If you are certain the DB is correct and files are “logically unchanged”: run
repairto update the recorded checksum(s) in schema history (or via the APIflyway.repair()), then re-run validation. [1] - If this started after upgrading Flyway and involves repeatable migrations/placeholders: check Flyway release notes and known issues; there have been reports of checksum mismatches appearing after minor upgrades in Spring Boot 3 + Flyway Java API scenarios. [5]
Sources:
[1] Redgate Flyway Docs — Validate (updated Feb 12, 2026)
[2] Flyway API/Javadoc — Flyway.validateWithResult() / ValidateResult usage
[3] Redgate article — Flyway “validate” command and checksum (CRC32) explanation
[4] Spring Boot API — FlywayMigrationStrategy
[5] Flyway GitHub issue report of checksum mismatch after upgrading (Spring Boot 3 + Java API)
🏁 Script executed:
rg -i "checksum\|FlywayValidateException\|flyway\.repair" --type javaRepository: PSMRI/AMRIT-DB
Length of output: 40
🏁 Script executed:
rg "FlywayMigrationStrategy|validateWithResult" --type javaRepository: PSMRI/AMRIT-DB
Length of output: 40
Narrow repair trigger to checksum-mismatch-only validation failures.
Line 46 currently catches all FlywayValidateException cases, and lines 47–51 run repair() for all of them when the flag is enabled. This is broader than the flag's intent and can mask non-checksum validation failures (e.g., missing migrations, invalid syntax).
Suggested approach: check the exception message for checksum-related content:
Option A: Helper method with message inspection
- } catch (FlywayValidateException e) {
- if (ignoreAppliedMigrationChecksum) {
+ } catch (FlywayValidateException e) {
+ if (ignoreAppliedMigrationChecksum && isAppliedChecksumMismatch(e)) {
logger.warn("Checksum mismatch detected for {}: {}. Repairing schema history...",
schemaName, e.getMessage());
flyway.repair();
flyway.migrate();
} else {
throw e;
}
}
}
+
+ private boolean isAppliedChecksumMismatch(FlywayValidateException e) {
+ String message = e.getMessage();
+ return message != null
+ && message.toLowerCase().contains("checksum");
+ }Alternative consideration: Flyway's validateWithResult() API provides structured validation details (ValidateResult.invalidMigrations) and does not throw, allowing precise filtering of checksum mismatches without message parsing. This may be a more robust path if a broader refactor is acceptable.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/db/piramalswasthya/config/FlywayMigrator.java` around lines
46 - 52, The catch block in FlywayMigrator currently treats all
FlywayValidateException cases the same when ignoreAppliedMigrationChecksum is
true; change this so we only call flyway.repair() and flyway.migrate() for
checksum-mismatch cases: either (A) inspect the FlywayValidateException message
for checksum-related text before repairing (only proceed if it indicates a
checksum mismatch), or (B) refactor to use flyway.validateWithResult() and
examine the returned ValidateResult.invalidMigrations entries to detect checksum
mismatches explicitly, and only then invoke flyway.repair() / flyway.migrate();
keep the ignoreAppliedMigrationChecksum flag logic and only narrow the trigger
to checksum-only failures.
| if (ignoreAppliedMigrationChecksum) { | ||
| logger.warn("Checksum mismatch detected for {}: {}. Repairing schema history...", | ||
| schemaName, e.getMessage()); | ||
| flyway.repair(); |
There was a problem hiding this comment.
@KadariPavani there is no need for repair.
If a particular migration is already applied, but if the checksum has changed, skip and proceed. That's all.
…s #117 Use validateOnMigrate(false) in FlywayConfig when the flag is enabled, so already-applied migrations with changed checksums are simply skipped. Removes repair() and exception handling from FlywayMigrator.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/com/db/piramalswasthya/config/FlywayConfig.java`:
- Around line 14-24: The property name ignoreAppliedMigrationChecksum is
misleading because it toggles Flyway.validateOnMigrate (disabling all
validations) in createFlyway; either rename the config key to something accurate
like amrit.flyway.skip-validation (and update `@Value` and any references to
ignoreAppliedMigrationChecksum) or add a clear Javadoc/comment on the
FlywayConfig.createFlyway method explaining that this flag disables all Flyway
validations (checksums, missing migrations, type mismatches, etc.) since Flyway
has no checksum-only toggle—pick one approach and apply it consistently across
configuration and docs.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main/java/com/db/piramalswasthya/config/FlywayConfig.javasrc/main/java/com/db/piramalswasthya/config/FlywayMigrator.java
Rename amrit.flyway.ignore-applied-migration-checksum to amrit.flyway.skip-validation since validateOnMigrate(false) disables all Flyway validation, not just checksum checks.
|



…es #117
📋 Description
JIRA ID:
When Flyway detects a checksum mismatch on an already-applied migration (e.g. after a comment edit, whitespace change, or line-ending normalization), it throws a FlywayValidateException and blocks application startup — even though the migration was already successfully executed and the database is in the correct state.
This change adds a configurable flag amrit.flyway.ignore-applied-migration-checksum that, when set to true, instructs Flyway to ignore checksum validation for migrations that have already been applied (ignoreMigrationPatterns("*:applied")). This allows the application to start normally without re-running or failing on previously successful migrations.
The flag defaults to false to preserve strict validation in production. It is exposed as an environment variable AMRIT_FLYWAY_IGNORE_APPLIED in Docker environments.
Files changed:
FlywayConfig.java — reads the flag and conditionally applies ignoreMigrationPatterns("*:applied") to all four Flyway beans (dbiemr, dbidentity, dbreporting, db1097identity)
application.properties — adds amrit.flyway.ignore-applied-migration-checksum=false as the default
common_docker.properties — adds amrit.flyway.ignore-applied-migration-checksum=${AMRIT_FLYWAY_IGNORE_APPLIED:false} for Docker/CI environments
common_example.properties — sets the flag to true for local development convenience
✅ Type of Change
ℹ️ Additional Information
How to test:
Apply a Flyway migration to the database.
Modify the SQL file slightly (e.g. add a comment or change whitespace) without changing the migration version.
With amrit.flyway.ignore-applied-migration-checksum=false (default): application fails with FlywayValidateException on startup — confirms the flag is off by default.
With amrit.flyway.ignore-applied-migration-checksum=true: application starts successfully, the already-applied migration is skipped, and no data is re-applied.
Docker usage:
Set the environment variable AMRIT_FLYWAY_IGNORE_APPLIED=true to enable the behaviour in containerised deployments without changing any property files.
Risk: None — the default value is false, so existing deployments are completely unaffected unless the flag is explicitly enabled.
Summary by CodeRabbit