liquibase / liquibase-gradle-plugin

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

Plugin breaks debugging from intellij #72

Closed bomgar closed 4 years ago

bomgar commented 4 years ago

This might be a bit exotic but if I specify more than one activity and a runList the debugging flags break the idea run. It is only a problem if I have more than one activity.

> Task :liquibaseUpdate
liquibase-plugin: Running the 'preLiquibaseRun' activity...
INFO 5/25/20, 2:40 PM:liquibase: Successfully acquired change log lock
INFO 5/25/20, 2:40 PM:liquibase: Reading from DATABASECHANGELOG
INFO 5/25/20, 2:40 PM:liquibase: Reading from DATABASECHANGELOG
INFO 5/25/20, 2:40 PM:liquibase: Successfully released change log lock
Liquibase Update Successful
liquibase-plugin: Running the 'liquibaseRun' activity...
ERROR: transport error 202: connect failed: Connection refused
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [:735]

After some experimentation I noticed that a JVM is spawned for all activities and the JVM args are passed to every jvm. So if I call setJvmArgs([]) in the runLiquibase method everything works fine.

Is there a use case to pass the jvm args to the liquibase exec?

Possible solutions

println with the jvm args [-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=38961])

stevesaliman commented 4 years ago

Since gradle's built in --debug-jvm flag and Idea's normal JPDA debugging option works for the vast majority of use cases, I don't think I want to add complexity to the plugin, but there are 2 ways to debug when you have multiple activities.

The --debug-jvm flag does work with multiple activities, you just need to start a new remote debugging session in Idea between the activities - the build will pause for you to do that.

The other way to handle it is to set up a custom system property to control debug mode, and create a slightly different remote debugging configuration in Idea. You can do this with the following:

  1. Create a new Remote Debugging configuration in Idea. Choose "Listen to remote JVM" as the debugger mode, and check "Auto restart" box. This would be in the project you're trying to debug, like Liquibase itself.

  2. Add the following to your build.gradle file:

    tasks.withType(org.liquibase.gradle.LiquibaseTask) {
    if ( System.getProperty('jpda.remote.debug', 'false') == 'true' ) {
      jvmArgs '-agentlib:jdwp=transport=dt_socket,server=n,address=127.0.0.1:5005,suspend=y'
    }
    }
  3. When you want to debug your activities, Make sure the debugger is running in Idea, and run your build with the debugging flag set to true. In this case, you'd run gradlew update -Djpda.remote.dbug=true. The name of the system property is completely flexible, it just needs to match what you've put in the build.gradle file.

bomgar commented 4 years ago

My current setup: The test task in gradle depends on liquibase. Idea is configured to use gradle to run tests. From inside idea I want to select a single test an run it in debug mode. (right click test -> debug) This is broken at the moment.

The easiest fix is to remove the dependency from the tests to liquibase. But that is annoying and if I'm not careful I might accidentally commit this.

The solutions you propose are less flexible and not practical. I would have to modify the run configuration every time I want to debug a single test.

bomgar commented 4 years ago

Unfortunately this doesn't work

tasks.withType(org.liquibase.gradle.LiquibaseTask) {
    jvmArgs[]
}

The debug args are preserved :disappointed:

stevesaliman commented 4 years ago

I understand your use case better now. It is strange that it is able to restart the JPDA client after the first activity but before the test itself, but it can't do it before the second activity.

I've pushed a version of the plugin that should do what you want. You'll need to add maven { url "http://oss.sonatype.org/content/repositories/snapshots" } to your buildscript block and update the version of the plugin to 2.0.4-SNAPSHOT.

I added a jvmArgs property to the liquibase extension, and defaulted it to the empty array, which is what should be used almost always. It can be overridden by adding `jvmArgs = [ 'some', 'arg', 'array'] to the liquibase block in build.gradle.

Ideally, I'd like this to be a method call instead of a variable assignment like the other two things in the block, but for now this should do.

bomgar commented 4 years ago

This works! Thank you :+1:

mriehl commented 4 years ago

Hi @stevesaliman any chance this could see a release soon? I need this in basically every project and company policy doesn't allow 3rd party snapshots 😅

stevesaliman commented 4 years ago

Version 2.0.4 of the plugin was just released. Happy debugging!