Git Product home page Git Product logo

Comments (23)

Whoops avatar Whoops commented on August 29, 2024 16

I stumbled on this issue trying to get the same thing working. After some trail and error, this is what I landed on, and it seems to work reliably, and the code is pretty clean.

liquibase {
    activities.register("main") {
        val db_url by project.extra.properties
        val db_user by project.extra.properties
        val db_pass by project.extra.properties
        this.arguments = mapOf(
                "logLevel" to "info",
                "changeLogFile" to "src/main/resources/migrations/changelog.yml",
                "url" to db_url,
                "username" to db_user,
                "password" to db_pass
        )
    }
    runList = "main"
}

from liquibase-gradle-plugin.

nbrugger-tgm avatar nbrugger-tgm commented on August 29, 2024 2

@charlesganza , @landsman
I created a jooq meta generator extension over at https://github.com/nitok-software/jooq-liquibase-extension

from liquibase-gradle-plugin.

sballance avatar sballance commented on August 29, 2024 2

Are there ever going to be examples for this? I've been struggling to get my liquibase gradle configuration set up correctly in my build.gradle.kts file. I was using the jetbrains liquibase plugin and wanted to switch to this plugin but I can't replicate my setup. This setup creates tasks for each registered activity, e.g. liquibaseMainUpdate and liquibaseLocalUpdate.

plugins {
    id("org.jetbrains.gradle.liquibase") version "1.5.2"
}

dependencies {
    liquibaseRuntime("org.liquibase:liquibase-core:4.27.0")
    liquibaseRuntime(libs.h2)
    liquibaseRuntime(libs.ojdbc)
    liquibaseRuntime(libs.mssqlJdbc)
}

liquibase {
    activities {
        all {
            properties {
                changeLogFile.set("./changelogs/changelog.yaml")
                changeSetAuthor.set("me")
                defaultSchemaName.set("my_schema")
            }
        }
        register("main") {
            properties {
                driver.set("oracle.jdbc.Oracle")
                url.set("jdbc:oracle:thin:@//localhost:1520/MYDB")
                username.set("me")
                password.set("pass")
            }
        }
        register("local") {
            properties {
                driver.set("org.h2.Driver")
                url.set("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")
                username.set("me")
                password.set("pass")
            }
        }
    }
}

from liquibase-gradle-plugin.

alexvas avatar alexvas commented on August 29, 2024 1

@Whoops how do you configure runtime dependency on liquibase?

UPD: Oh, I see. It is just liquibaseRuntime dependency. No more buildscript classpath mangling.

from liquibase-gradle-plugin.

Chubacca avatar Chubacca commented on August 29, 2024 1

When using the code from @Whoops I ran into this issue even on liquibase 3.6.3. If I run the exact same thing in just a normal gradle file (not kotlin DSL) I don't run into these issues. This doesn't work in a build.gradle.kts file:

liquibase {
    activities.register("development") {
        this.arguments = mapOf(
            "changeLogFile" to "src/main/db/db.yaml",
            "url" to "jdbc:postgresql://localhost/test",
            "username" to "test",
            "password" to "test"
        )
    }
}

But this DOES work in a build.gradle file:

liquibase {
    activities {
        development {
            changeLogFile 'src/main/db/db.yaml'
            url 'jdbc:postgresql://localhost/test'
            username 'test'
            password 'test'
        }
    }
}

I ended up fixing it by adding these two lines into my build.gradle.kts:

liquibaseRuntime("ch.qos.logback:logback-core:1.2.3")
liquibaseRuntime("ch.qos.logback:logback-classic:1.2.3")

I'm not sure what's going on or why it might be different, but now everything works.

from liquibase-gradle-plugin.

nbrugger-tgm avatar nbrugger-tgm commented on August 29, 2024 1

De I am currently in the phase "bashing my head against the wall trying to wire 4 technologies together"

I will most probably write my own shitty gradle plugin that does the
testcontainers + liquibase + jooqGen chain. I (funny enought) already have a completely working process but the code is very confusing and not in one place

For everyone who does not care and just want to make it work:

  1. Copy the class LiquibaseDatabase from the jooq-meta-liquibase project.
  2. Rip out the old connect method
    3.replace it with your specific Database container start
  3. Wire it together with the jooqAutogen plugin as databaseclass

This is a Very watered down version you will still need to do things on order to have all the dependencies, and so on compile in the right order so that jooq has your compiled testcontainers dB. If anyone is interested I can share more.

BUT there is light on the horizon!!
If you look at the master branch of jooq you will see a JOOQ-gradle-plugin folder. Not yet documented but maybe in a far off dream world it will support our useCase as maven already does

from liquibase-gradle-plugin.

nbrugger-tgm avatar nbrugger-tgm commented on August 29, 2024 1

Oh I see what you mean. My plugin is meant for Jooq (in conjunction with liquibase) so it only works for the jooq autogeneration. This is not a general/generic "liquibase-gradle" thing. I should have stated this more clearly since we are in a liquibase issue and not jooq!

For a purely liquibase setup connecting to a real database can of course be beneficial. But the specific use case my plugin works for (jooq autogeneration with liquibase and testcontainers) does not benefit from a Prod dB.

On a more general note, in my opinion it's not the job of a plugin author to support spring specific variable substitution or some other format. The way gradle works you can find a plugin or write it yourself that can read a yml/properties file do the substitution and then feed it into said plugin. (with my plugin this would work as long as you encode it as a full URL including user and password but as I said this is not a use case for my plugin anyway)

Example

somePluginThatRequiresPasswordAndUser {
    var props = new Properties();
    props.load(FileInputStream("pathRoFile);
    jdbcUrl= props.get("spring.data.nameOfYourSpecificDatasource.url");
}

This example doesn't do substitutions but it shouldn't be to hard to get it working and there is probably a library/gradle plugin. But reading a spring config file will full spring SPEL support is not that easy and a different issue.

from liquibase-gradle-plugin.

stevesaliman avatar stevesaliman commented on August 29, 2024

Thank you for raising this issue.

From a quick glance at the linked documentation, it looks like the issue is in the plugin itself. It does indeed expect a closure to create each activity. I'll need to look at the documentation more closely and see if I can update the plugin according to its recommendations.

Until I'm able to update the plugin, it probably won't work right with Kotlin build files.

from liquibase-gradle-plugin.

mstawick avatar mstawick commented on August 29, 2024

Thanks @Chubacca , your comment really helped me (BTW, Java13, Gradle 6.1).

from liquibase-gradle-plugin.

fabio-filho avatar fabio-filho commented on August 29, 2024

@Whoops ,
I don't know why, but the delegation does not works. I only get the excepted value when I access the properties directly by the key.

image

from liquibase-gradle-plugin.

charlesganza avatar charlesganza commented on August 29, 2024

To those using test containers:

val testContainer = PostgreSQLContainer("postgres:latest")
	.apply {
		withDatabaseName("liquibase-db")
		withUsername("user")
		withPassword("testing")
		start()
	}

liquibase {
	activities.register("main") {
		this.arguments = mapOf(
			"logLevel" to "info",
			"classpath" to "${project.rootDir}/application/src/main/",
			"changeLogFile" to "resources/db/changelog-main.xml",
			"url" to testContainer.jdbcUrl,
			"username" to testContainer.username,
			"password" to testContainer.password,
			"driver" to "org.postgresql.Driver"
		)
	}
	runList = "main"
}

Extra config when using JOOQ:

tasks.named("generateJooq").configure {
	dependsOn(tasks.named("update"))
	doLast {
		testContainer.stop()
	}
}

from liquibase-gradle-plugin.

landsman avatar landsman commented on August 29, 2024

There is still not a good example I see. What am I missing is also option how to load configuration from properties.

from liquibase-gradle-plugin.

nbrugger-tgm avatar nbrugger-tgm commented on August 29, 2024

@charlesganza also this example is problematic because it eagerly starts the container in the configuration phase. This means that even if you do ./gradlew :tasks it will start a docker database container or even worse, fail if the person has no internet or no docker

from liquibase-gradle-plugin.

charlesganza avatar charlesganza commented on August 29, 2024

@nbrugger-tgm
Yes, this example assumes the user has Docker installed and is connected to the internet. I added it in case it could help someone else, and it works well enough in my case.
You're more than welcome to improve on this approach :)

from liquibase-gradle-plugin.

landsman avatar landsman commented on August 29, 2024

@nbrugger-tgm are you using spring framework, spring boot? I don't like that configuration with db details in gradle task when I have this convered already in property / yml files for spring. It would be great to support it.

from liquibase-gradle-plugin.

nbrugger-tgm avatar nbrugger-tgm commented on August 29, 2024

@landsman spring has little to do with this. Spring is a runtime framework. Jooq autogenes is purely compile time the database you use for prod&testing has nothing to do with your compile process.

The jdbc:tc URL only exists to tell testcontainers which docker image to use for the autogeneration.

Could you specify how you think this should work with spring?

from liquibase-gradle-plugin.

landsman avatar landsman commented on August 29, 2024

Could you specify how you think this should work with spring?

just put there path to property file and support replacement for env variables, for example:

spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASS}
spring.datasource.url=jdbc:postgresql://${DB_HOST}:5432/mydb

from liquibase-gradle-plugin.

nbrugger-tgm avatar nbrugger-tgm commented on August 29, 2024

This makes no sense to me.

Why would you need your Gradle/build process to connect to a real dB? Why would gradle need password and username on an empheral container?

The string jdbc:tc:mysql:8:/localhost does not mean "connect to localhost". The "tc" stands for testcontainers and makes it so that when JDBC gets the URL testcontainers will start a temporary mysql:8 docker Container on localhost that is used to generate the jooq schema. If you look at the "example" in my repo you see that there is no user or password because the container doesn't need it. You can even remove the localhost part. Here is the official docs : https://java.testcontainers.org/modules/databases/jdbc/

from liquibase-gradle-plugin.

landsman avatar landsman commented on August 29, 2024

I can use it to generate diff with real db for example.

from liquibase-gradle-plugin.

stevesaliman avatar stevesaliman commented on August 29, 2024

If you put the properties in gradle.properties, you don't need to load a file, you can just refer to the project property. For example, if you have a property named jdbcUrl in gradle.properties, your liquibase block can look like this:

liquibase {
    activities {
         main {
            driver project.ext.jdbcDriver
            url project.ext.jdbcUrl
            username project.ext.jdbcUsername
            password project.ext.jdbcPassword
            changeLogFile "master.groovy"
        }
}

If you need different properties for different environments, you could use https://github.com/stevesaliman/gradle-properties-plugin, which lets you store different values in various gradle-.properties files

from liquibase-gradle-plugin.

asm0dey avatar asm0dey commented on August 29, 2024

@nbrugger-tgm the jitpack version does not build :(

from liquibase-gradle-plugin.

nbrugger-tgm avatar nbrugger-tgm commented on August 29, 2024

@asm0dey fixed it: nitok-software/jooq-liquibase-extension#1 should work now 👍🏻

Also if you have problems with my code/extension you should open an issue there and not here

from liquibase-gradle-plugin.

landsman avatar landsman commented on August 29, 2024

@sballance I had no idea about the existence of Jetbrains plugins, thanks for the link!
Why do you want to switch?

By the way, I left this alone and started using JPA Buddy.

from liquibase-gradle-plugin.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.