liquibase / liquibase-gradle-plugin

A Gradle plugin for Liquibase
Other
197 stars 57 forks source link

Load parametrs from application.yml #85

Closed kulemeevag closed 2 years ago

kulemeevag commented 3 years ago

I need get props from my application.yml file and use for plugin in build.gradle. How can I achieve this?

liquibase {
    activities {
        main {
            changeLogFile "$projectDir/src/main/resources/db/db.changelog-master.xml"
            url props.getProperty('spring.datasource.url')
            driver props.getProperty('spring.datasource.driver-class-name')
            username props.getProperty('spring.datasource.username')
            password props.getProperty('spring.datasource.password')
        }
    }
}

I tried use, but nothing: def props = new org.yaml.snakeyaml.Yaml().load( new File("application.yml").newInputStream() ) Gradle can't resolve Yaml. org.yaml:snakeyaml:1.25 included by spring-boot-starter-parent. I try add org.yaml:snakeyaml:1.25 to my dependency manual. Not fixed error.

P.S.: liquibase: 3.8.6 liquibase-plugin: 2.0.4 spring-boot-starters: web, data-jpa

stevesaliman commented 3 years ago

I was able to get this working with by doing the following:

  1. I added the snakeYaml as a classpath dependency in the buildscript block of your build.gradle file.
  2. I added a line to the my liquibase block to load the application.yml file. I did need to add a path to the file before it was found. I put this line at the beginning of my liquibase block, but I think you could also put it inside the main block.
  3. I changed the url, driver, etc. to lines like this: username props.spring.datasource.username. For some reason, calling props.getProperty didn't work for me.

Does this solve your problem?

kulemeevag commented 3 years ago

I was able to get this working with by doing the following:

  1. I added the snakeYaml as a classpath dependency in the buildscript block of your build.gradle file.
  2. I added a line to the my liquibase block to load the application.yml file. I did need to add a path to the file before it was found. I put this line at the beginning of my liquibase block, but I think you could also put it inside the main block.
  3. I changed the url, driver, etc. to lines like this: username props.spring.datasource.username. For some reason, calling props.getProperty didn't work for me.

Does this solve your problem?

@stevesaliman, thanks for your answer. Yes, it worked if add

buildscript {
    dependencies {
        classpath group: 'org.yaml', name: 'snakeyaml', version: '1.25'
    }
}

Maybe it will help someone: For parameter changeLogFile need use props.spring.liquibase."change-log"

But now I have 3 problems:

  1. In my application.yml:
    spring:
    liquibase:
    change-log: classpath:migrations/migrate.xml

    But when I use liquibase plugin I have error liquibase.exception.ChangeLogParseException: classpath:migrations/migrate.xml does not exist. Resolved by adding props.spring.liquibase."change-log".replace('classpath:','src/main/resources/'). Not sure if this is a good solution.

  2. If in application.yml has something ${variable}, then I use replace function. Not sure if this is a good solution.
  3. It big problem. Need load merged application.yml with application-.yml.
stevesaliman commented 3 years ago

If you want to use a classpath resource, you need to have liquibaseRuntime sourceSets.main.output in your dependencies block, and you need to make the liquibase task you're trying to use dependent on processResources with something like update.dependsOn processResources so that the file is in the right place when Liquibase runs.

I think your larger issue is the fact that you're trying to replicate what Spring Boot does when it processes yaml files in your build script. Spring has a lot of code to load the right files in the right order, making all the variable substitutions for you.

There are two ways I could see to possibly address the issue. You could make sure all the liquibase properties you need are in the application-whatever.yml file, then you wouldn't have the merging problem. You could also use the Gradle Properties Plugin to define profile specific properties for Gradle and skip loading the application.yml file altogether. Neither is a perfect solution, but they'd work.

Out of curiosity, if you're using Spring Boot, why not just let Spring Boot run liquibase for you when the application starts? That way you don't need to worry about Gradle properties, and Spring will just use the application*.yml files in the normal manner.

kulemeevag commented 3 years ago

Plugin I use, then want check migration. For example rollback case. Yes, then Spring Boot start application, he run migration.

Thanks, for your answer