Applying Liquibase migrations for integration tests on a multi module gradle project

1.4k Views Asked by At

I am modularising a monolith developed in Java, It utilizes the Micronaut framework and Gradle as a Build tool. As the title suggests, It utilizes Liquibase for database migrations.

The old structure:

It's a standard single Gradle java project with the war plugin to generate a war file. It has all the migrations in the src/main/java/resources folder (standard micronaut-liquibase stuff)

The new structure:

I am breaking down various independent domains into separate Gradle projects. And I have made a startup project which should have all the project initialization logic like Micronauts context init and Liquibase DB migrations.

project/
|
+---gradle-project-A/
|   |
|   +---build.gradle
|   |
|   +---src/main/java/
|   |
|   +---src/test/
|       |
|       +---java/TestIntegration.java
|       |
|       +---resources/application.yml (for testing)
|
+---startup/
|   |
|   +---build.gradle
|   |
|   +---src/main/java/Application.java
|   |
|   +---src/main/java/resources/
|       |
|       +---db/changelog.sql files (These files are referred by the changelog.yml)
|       +---liqiubase-changelog.yml (Liquibase looks for this file in classpath)
|       +---application.yml (Micronaut config)
|
+---settings.gradle
|
|

Of course, there will be many more Gradle projects gradle-project-B, C...

Ultimately, The startup will produce a war file that will include gradle-project-A as a jar dependency. This is the structure I thought of.

so, startup depends on every other Gradle project

a stripped-down version of startup/build.gradle

plugins {
    'io.micronaut.application'
    'war'
}

dependencies {
    implementation project(':gradle-project-A')
}

The Problem

  • As the folder structure suggests, there are Integration tests that require all the liquibase migrations to be pre-applied to the database (test container)
  • In the old structure the migrations were picked up while executing tests because they were in the same Gradle project.
  • Now, the migrations are part of startup and they are obviously not being picked up while running Integration Tests in gradle-project-A

My Research so far

  • The new project structure was inspired by this post
  • My question seems similar to this question on StackOverflow but I am not sure I understand it correctly (Not a Gradle expert)

The Question

  • How do I get gradle-project-A to detect liqiubase-changelog.yml in the classpath while running tests?
  • I can't have startup as a dependency of gradle-project-A as that will be a circular dependency. Can my module structure be improved?

Any suggestions from your side are welcome! Thanks for the help in advance...

2

There are 2 best solutions below

2
Spasoje Petronijević On

I would say that you need to split your migration scripts for project-A, project-B, etc.

So, inside project-A/src/main/java/resources/ you need to have migration scripts for project-A, same for project-B, etc. Then, inside your startup project you can have changelog.xml which looks like this:

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

    <include file="pathToChangeLogFromProjectA.xml" relativeToChangelogFile="true"/>
    <include file="pathToChangeLogFromProjectA.xml" relativeToChangelogFile="true"/>

</databaseChangeLog>

This way, startup will pick migration scripts for all projects and when you run tests for project-A, only scripts for that project will be run.

0
Grigory Kislin On

You should create changelog file not for module, but for DB (some modules may share one DB). Then you may keep changelogs in shared configuration (see Change working directory for gradle multi-module project) and declare path to changelog module's DB in every needed module. For Spring Boot it could be looks like (in application.yaml):

spring.liquibase:
   changeLog: "file:${PROJECT_ROOT}/config/db/migration/db_a.sql"