简体   繁体   中英

Liquibase with Gradle - silly problem with changeLogFile path

I'm stuck with a silly but annoying problem with implementing Liquibase to my existing project. After a lot of struggling I got it to work when starting the application, it runs through the master changelog and the included changelogs/changesets.

The problem then occurred when I was adding the Luquibase Gradle plugin (which also is needed for future support) because the can't find the changelog file with the same path.

When running the application through settings in application.yml file the changelog needs to be:

changeLog: classpath:/db/changelog-master.yml

to work (else the file can't be found) and the path in my changelog-master file is:

databaseChangeLog: - include: file: db/changelog/changelog.yml

But if I use plugin commands (changelogSync for example) the path needs to be from the src, like:

src/main/resources/db/changelog-master.yml

for the plugin to find the changelog.

Would really appreciate some help to be able to use Liquibase both when starting the application and when using commands with the plugin but I can't seem to find a way around this silly thing.

My activities in build.gradle is like this:

liquibase {
activities {
    main {
        File propsFile = new File("${project.rootDir}/src/main/resources/liquibase.properties")
        Properties properties = new Properties()
        properties.load(new FileInputStream(propsFile))
        changeLogFile properties['changeLogFile']
        url properties['url']
        username properties['username']
        password properties['password'] 
     }
  }
}

And the Liquibase setup in application.yml is:

  spring:
   liquibase:
   enabled: true
   changeLog: classpath:/db/changelog-master.yml

There just must be an easy solution to this that I just can't seem to find? Feel free to ask for more code snippets but the rest is quite straightforward according to the documentation from Liquibase with the liquibase.propterties file etc in my setup. I'm using Liquibase core v. 3.8.9 and plugin version 2.0.3.
Thanks.

I am not able to understand your question 100% but I think below solution will do the job for you to configure multiple class paths for liquibase

I think it'd be a good idea to make the following structure:

--src
   -- main
     -- resources
       -- changelogs
          -- migrations1.xml
          -- migrations2.xml
          -- ...
          -- migrationsN.xml
       -- migrations.xml (it's a master changeLog which includes all the other changeLogs)

Try setting relative path to your child changeLog files as such:

<includeAll path="/changelogs" relativeToChangelogFile="true"/>

In the first link on includeAll docs there's a part about why it's not a very good practice to use it

While the includeAll tag has many valuable uses, its use can cause problems down the road. The biggest thing to avoid is to use the includeAll tag to simulate Ruby on Rails Active Migrations strategy of a list of changes, one per file, that are ran in file order. While this seems like a good idea at first, it quickly runs into problems

If you do choose to use the includeAll tag, make sure you have a naming strategy in place that will insure that you will never have conflicts or need to rename files to change to force a reordering.

so perhaps you may consider using <include> tag and list all the child changeLog files.

EG:

<include path="changelogs/migrations1.xml" relativeToChangelogFile="true"/>
<include path="changelogs/migrations2.xml" relativeToChangelogFile="true"/>
...etc.

I can belatedly offer a workaround which I've found. I experienced a similar issues to what you described, which I've captured in detail in the Liquibase community . I am using liquibase version 4.3.2 and Gradle plugin 2.0.3.

In my example, I was using a.xml master including mysql.sql files

./src
└── main
    ├── java
    └── resources
        ├── application.properties
        └── db
            └── changelog
                ├── init
                │   ├── 1-0-table.mysql.sql
                │   └── 1-0-view.mysql.sql
                └── master.xml

master.xml

<?xml version="1.0" encoding="UTF-8"?>   
<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.8.xsd">  

  <include  file="init/1-0-table.mysql.sql"
            relativeToChangelogFile="true" />

  <include  file="init/1-0-view.mysql.sql"
            relativeToChangelogFile="true"
            context="!test"/>

</databaseChangeLog>

After moving to a.yml master including.yml files, I have been able to run the updates without any conflict from the classpath prefix, even though the classpath prefix is only used in spring.

./src
└── main
    ├── java
    └── resources
        ├── application.properties
        └── db
            └── changelog
                ├── init
                │   ├── 1-0-table.yml
                │   └── 1-0-view.yml
                └── master.yml

master.yml

databaseChangeLog:
  - include:
      file: init/1-0-table.yml
      relativeToChangelogFile: true
  - include:
      file: init/1-0-view.yml
      relativeToChangelogFile: true
      context: "!test"

But if I use plugin commands (changelogSync for example) the path needs to be from the src, like:

To resolve this issue, you can configure the classpath base directory in the Liquibase task that is run by Gradle.

This will ensure that the relative paths match after stripping this base path:

/src/main/resources/ db/changelog/changelog.yml = db/changelog/changelog.yml

Also it resolves your issue with migration duplicating after «explicit point out the changlogFile in "Build.Gradle"»

Full config should be something like below (for you case):

liquibase {
  activities {
    main {
        File propsFile = new File("${project.rootDir}/src/main/resources/liquibase.properties")
        Properties properties = new Properties()
        properties.load(new FileInputStream(propsFile))
        changeLogFile properties['changeLogFile']
        url properties['url']
        username properties['username']
        password properties['password']
        classpath "${projectDir}/src/main/resources"
     }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM