"runalways" changesets seem to break rollback functionality

Liquibase Version: 3.5.3
Database: PostgreSQL 9.3.15
OS: Windows 10

I am seeing strange behaviour when trying to utilise the "runalways" attribute on changesets. I am using liquibase in the following way (simplified example):

Master Changelog


I have now lost my tag of "build-1" that would have let me rollback changeset "updates-3" as the databasechangelog record that was tagged with "build-1" has been been "RERAN", and had it's dateexecuted value updated. When the tag of "build-2" was applied, it then updated the "always-1" databasechangelog record.

Is this a bug, or am I misunderstanding the way in which the tags work with liquibase?

Thanks.

The tag change updates the last executed changeset in your history table. That beeing said it’s a bad idea to tag from outside (as it appears in your case, cause I can’t see any tag change in your changeSets).

My advice would be to add a explicit changeSet with only a tag change, so you can make sure the tag is exactly on this entry in the history table. While that does not help you in the case if you are adding more changeSets before that one (then rollback will still be broken), but that seems to be a design decision of liquibase (not to complain about changeSets out of order).

What about using the changeLog Parameter within the changeSet name, something like this:

You will lose the ability to see the tagging changeSets physically in the ChangeLogFile, but you will get the tags you want.

Hi Sam,


good point, didn’t think about that.
Just a wild guess, you may add a rollback to your tagging ChangeSet, that does the cleanUp in the Liquibase History Table for you.

I see this is pretty raw especially as it may cause problems when the buildnumbers do not fit into string comparison (jumping from 999 to 1000, comparing real numbers is certainly better but i guess you get the idea). and you’ll still have to pass the targeted build number around… but I don’t see how this can be fixed.

kind regards
Daniel

Thanks Daniel.


We currently have the tag being performed after the liquibase update from a Bash script in production, e.g.:

java -jar ${LIQUIBASEJAR} --driver=${LBDRIVER} --classpath=${LBCP} --url=${LBURL} --username=${LBUNAME} --changeLogFile=${LBCHANGELOG} tag ${BUILDNO}

This way, whenever we install a build, we get the tag of the build number added at the end of the update process. I tried adding in a single changeset to tag the database state in between my usual updates and my “runalways” updates using the changelog params to pass in the build number to the changelog , e.g.:

I can’t help but feel that I must still be missing something, as I’m not convinced that this is a particularly obscure use case.

Daniel,

Thanks for your help, that is certainly a lot better than what I currently have!

There is still a small issue with the functionality, but I am convinced that it should not pose to much of a problem for my usage

The databasechangelog record for the tag operation will not be removed when performing a rollback operation unless I make sure I pass the same ${build.number} value in to the liquibase command. Otherwise, liquibase would perform in the same way as if it couldn’t find the changeset in my changelog, and skip it during rollback.

Take the following scenario as an example:

  1. Update to build 1
  2. Update to build 2
  3. Update to build 3
  4. Rollback to build 1
  5. Update to build 3

At step 4, I would only have 3 databasechangelog records, one for each of the tag commands.

At step 5, the changeset for tagging build 3 would be bumped to the top/end again, but the changesets for tag 1 and 2 would be left at the bottom/start of the databasechangelog.

If I now attempt to rollback to build 2, It would rollback all of the changesets (or at least the same amount as trying to rollback to build 1). 

As I said, not a big deal to me, but thought it worth adding here.

Thanks again.

Thanks again Daniel.

Think I have enough to work around the issue for my needs.

Cheers.