liquibase / liquibase-gradle-plugin

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

tagExists doesn't work #51

Closed PI-Victor closed 5 years ago

PI-Victor commented 5 years ago

If you execute gradle tagExists -PliquibaseCommandValue=v1.0.0 on a database that you tagged with gradle tag -PliquibaseCommandValue=v1.0.0 the command doesn't return anything. Nor does it complain if you check for a tag that doesn't exist at all, in this case, tag v1.0.1.

Here's my DATABASECHANGELOG entry with the current tag:

+------------------+--------+----------------------------------------+---------------------+---------------+----------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------+-------------+-----------+----------+--------+---------------+
| ID               | AUTHOR | FILENAME                               | DATEEXECUTED        | ORDEREXECUTED | EXECTYPE | MD5SUM                             | DESCRIPTION                                                                                                                              | COMMENTS | TAG         | LIQUIBASE | CONTEXTS | LABELS | DEPLOYMENT_ID |
+------------------+--------+----------------------------------------+---------------------+---------------+----------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------+-------------+-----------+----------+--------+---------------+
| 1540907006515-53 | xxxx    | my-changeLog | 2018-11-16 11:08:43 |            53 | EXECUTED | xx:xxxx | addForeignKeyConstraint baseTableName=xxxxx, constraintName=xxxxx, referencedTableName=xxxx |          | v1.0.0-beta | 3.6.2     | NULL     | NULL   | 2366518615    |
+------------------+--------+----------------------------------------+---------------------+---------------+----------+------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+----------+-------------+-----------+----------+--------+---------------+

Check for an existing tag

/db # gradle -i tagExists -PliquibaseCommandValue="v1.0.0-beta"
Initialized native services in: /root/.gradle/native
Using 1 worker leases.
Starting Build
Settings evaluated using settings file '/db/settings.gradle'.
Projects loaded. Root project using build file '/db/build.gradle'.
Included projects: [root project 'db']

> Configure project :
Evaluating root project 'db' using build file '/db/build.gradle'.
All projects evaluated.
Selected primary task 'tagExists' from project :
Tasks to be executed: [task ':tagExists']
:tagExists (Thread[main,5,main]) started.

> Task :tagExists
Task ':tagExists' is not up-to-date because:
  Task has not declared any outputs despite executing actions.
liquibase-plugin: Running the 'main' activity...

REMOVE OUTPUT

Successfully started process 'command '/usr/lib/jvm/java-1.8-openjdk/bin/java''
Starting Liquibase at Thu, 22 Nov 2018 21:11:13 GMT (version 3.6.2 built at 2018-07-03 11:28:09)
Liquibase command 'tagExists' was executed successfully.
:tagExists (Thread[main,5,main]) completed. Took 1.053 secs.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
See https://docs.gradle.org/4.8.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed

Checking for a bogus database tag

/db # gradle -i tagExists -PliquibaseCommandValue="v1.0.0-beta1"
Initialized native services in: /root/.gradle/native
Using 1 worker leases.
Starting Build
Settings evaluated using settings file '/db/settings.gradle'.
Projects loaded. Root project using build file '/db/build.gradle'.
Included projects: [root project 'db']

> Configure project :
Evaluating root project 'db' using build file '/db/build.gradle'.
All projects evaluated.
Selected primary task 'tagExists' from project :
Tasks to be executed: [task ':tagExists']
:tagExists (Thread[main,5,main]) started.

> Task :tagExists
Task ':tagExists' is not up-to-date because:
  Task has not declared any outputs despite executing actions.
liquibase-plugin: Running the 'main' activity...

REMOVED OUTPUT

Successfully started process 'command '/usr/lib/jvm/java-1.8-openjdk/bin/java''
Starting Liquibase at Thu, 22 Nov 2018 21:11:25 GMT (version 3.6.2 built at 2018-07-03 11:28:09)
Liquibase command 'tagExists' was executed successfully.
:tagExists (Thread[main,5,main]) completed. Took 1.05 secs.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
See https://docs.gradle.org/4.8.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed
stevesaliman commented 5 years ago

I'm not exactly sure what to do with this one. This behavior is obviously not what we want, but the root of the problem appears to be in Liquibase itself.

When Liquibase executes the tagExists commane, it checks for the tag, and based on whether or not it exists, it simply outputs that fact. You can see this behavior if you add mainClassName 'org.liquibase.gradle.OutputEnablingLiquibaseRunner' to your liquibase block in build.gradle. The out put changes based on whether the tag does or doesn't exist.

The problem is that Liquibase doesn't return anything different based on the tag, so there isn't anything the plugin can easily detect to branch based on the existence of the tag. And there is an argument to be made that if Liquibase itself doesn't return an error for a bad tag, neither should the plugin, which makes some sense. After all, the command is meant to check and report if the tag exists, which it does.

The difficulty in getting output from recent versions of Liquibase, doesn't help matters, and issue CORE-3220 has been reported in the Liquibase JIRA to address it.

PI-Victor commented 5 years ago

@stevesaliman thank you for the description. Not sure what to do with this issue now, should i close it (since it's unrelated to the actual plugin) and open it on the actual liquibase repo. Or, given that there's that bug you linked above, that should suffice? My main problem is, that in order to integrate liquibase into a ci/cd pipeline, i'd need tagExists to make sure devs are not overwriting the latest tag with the same. Otherwise, you could gradle tag with whatever version you want.

stevesaliman commented 5 years ago

I'm not sure where to go with it either. I agree that we should probably close the issue here, at least until Liquibase changes its behavior. We can always re-open it at that time if we need to change the plugin to work with new Liquibase functionality.

The linked JIRA was just an issue with the way output works. I think we need a new JIRA for the tagExists issue.

I think the main question is whether or not the existence of a tag should be a problem or not when we either create or query a tag. Based on your use case, I think the actual problem is with the tag command. It seems to me that the default behavior should be to fail if the tag already exists, with an extra parameter that could tell Liquibase to force the creation if you don't care that you're overwriting an existing tag.

I don't have the Liquibase code in front of me at the moment, but I'll take a look at it this evening to make sure the code doesn't already try to do this. I just want to make sure the plugin isn't ignoring some kind of Liquibase functionality before we create a new JIRA

stevesaliman commented 5 years ago

I just took a look at the Liquibase code, and sure enough, the only thing the plugin does differently is logging. I definitely think Liquibase should allow us to specify what we want to do when that happens.

PI-Victor commented 5 years ago

alright, i will 'migrate' this issue to the liquibase core repository.

i agree with your thought on tag behaviour, i think the expected behavior should be for liquibase to at least throw an exception when you try to apply an already existing tag, this will avoid people accidentally overwriting db schema with the same version.