Hi all, I'd like to propose a small CI check for Liquibase changelog registration and get your thoughts before I start working on it. The problem
Every changelog part must be registered with an <include> in a master changelog (changelog-tenant.xml or a module's module-changelog-master.xml). If that include is accidentally removed—for example, while resolving a merge conflict near the end of a master changelog—the part is never executed. The problem is that nothing fails during the Liquibase migration itself. The failure often surfaces later in seemingly unrelated tests, which makes the root cause difficult to identify. This happened in one of my PRs (#6124). A merge conflict resolution dropped the include line, and all database shards subsequently failed with: Configuration property 'disallow-backdated-transactions' does not exist There was nothing in the failure output that pointed back to the missing changelog registration. What's already in place, and why it doesn't cover this - *Verify Liquibase Backward Compatibility* checks the changesets that actually run. An unregistered part never runs, so there is nothing for it to validate. - *Regression Safety - Database Changes* replays migrations from the base branch to the PR and similarly skips an unregistered part. - *check-liquibase-ddl-safety.sh* inspects DDL in changed files, but does not verify whether a changelog file is registered. - *Liquibase's own validation* only sees files reachable from the master changelog, so an orphaned file remains invisible. - Switching to *includeAll* would remove the manual registration step, but it introduces ordering concerns. Our part numbers are not globally unique or consistently increasing, so a fresh installation and an upgraded database could potentially execute files in different orders. Explicit includes also carry contexts such as initial_switch. The proposal Add a script, following the same approach as check-liquibase-ddl-safety.sh—*bash and grep only, with no new dependencies*—and run it on PRs that modify db/changelog. The check would: - *Fail* if a changelog part is not included by any master changelog. - *Fail* if a changelog part is included more than once. - *Fail* if an <include> points to a file that does not exist. - *Warn*, but not fail, if a new part reuses a number already present on develop. The script would discover the master changelogs itself and resolve each include relative to its master. This would cover fineract-provider (tenant and tenant-store) as well as all modules, including the different folder layout used by fineract-savings. On develop today, there are *429 parts across 9 changelog trees*, and every part is included exactly once. The check would therefore pass against the existing codebase without requiring a list of exceptions. For example: ERROR fineract-provider/tenant: parts/0255_add_example_column.xml is not included by any master changelog WARN fineract-provider/tenant: parts/0254_add_example_config.xml reuses 0254, which develop already uses A note on numbering At the time of writing, there are *19 open PRs adding a changelog part*. - 10 use a number that develop already has, which the proposed warning would flag. - Another 6 share an unused number with a different open PR. For example, five PRs currently want 0255. A check against develop alone would not detect those conflicts. Questions I'd appreciate your thoughts on a few points: 1. Would this check be useful to you? 2. For reused changelog numbers, should the check *warn, fail, or ignore* them? develop already contains duplicate numbers such as 0242 and 0243, and they work correctly, so the main cost of enforcing uniqueness would be the need to renumber during rebases. 3. Should this be implemented as a *separate workflow*, or as a step in one of the existing Liquibase workflows? Once there's some rough agreement, I'll open a JIRA ticket and follow it up with a PR. Thanks, Abhishek Chaudhary
