Liquibase: How do I manage different branches with one database - liquibase

I have the following problem:
I am working on two different branches: dev, feature1
Both branches work on the same database schema.
Imagine I have changelog-v1.0 on my dev-branch und my database fits to that version.
Now if I have changelog-v1.1 on my feature1-branch and start my app from there liquibase will apply thhis changes to my database.
From this moment on my app on dev-branch will not work anymore, because even though there is no changelog-v1.1 on the dev-branch, the database is already migrated to that version
and if I start my app on the dev-branch liquibase will not roll back the changes of changelog-v1.1.
Working on many branches with different changelog but just one database.
How do I manage this?

You can have a master changelog file pointing to children changelog files. But need to make sure to have same files in all branches that have to be merged from dev to feature branch.
Also, note that you have rollback code and tagging in the liquibase changesets in order to successfully rollback changes.

Related

Liquibase: Deleting Sql File used in Changeset

we are using liquibase for our DB-Deployment. We are currently doing some refactoring. There is an old changeset which is running an sql script. This has been executed in the past. Now this sql script (or the statement in it) is outdated and I would like to deleted from our VCS System. I did that and tried to deploy again, but I am getting an exception saying that the sql file is not there, although my Changeset has runAlways="false" and runOnChange="false".
Does this mean that I have to always keep the specific sql script always in my CVS although it is deprecated?
According how checksum works on Liquibase, you can't delete it. Technically you run that changeset one time, and something happened on DB, then liquibase created a checksum for your file. Now if you change some part of it, liquibase will say your file is updated and you can't do that.
So in summary, your file is part of the story of your application build, even if it is no longer useful, and you can't get rid of it.
If you are not in production case, one solution could be create a dump from your current database as init.sql and start from that.
I hope this helps you.

Liquibase: runOnChange + rollback

According to Liquibase docs stored procs/triggers etc should be stored separately in a single copy and added to changeset with runOnChange to update them for each change. But what is a recommended way to rollback to the previous change? The only idea that I have is to copy them to a separate folder for each release and add apply operation of this version as a rollback (for example, have sql\procs\current for last version all added to changelog as apply and sql\procs\1.0.0 is a copy of sql\procs\current when we started new 1.0.0 release). Are there any best practices for it?
Thanks!
We keep single copy of replaceable objects (procs/triggers/views etc)
and use version control system (VCS) - git in our case.
When you want to rollback to previous version, just revert to relevant commit in VCS and run liquibase update.
Tutorial using Oracle - we are working by this tutorial for two years.

Can Liquibase detect if it has already run?

I have a small set of scripts that manage the build/test/deployment of an app. Recently I decided I wanted to switch to Liquibase for db schema management. This script will be working both on the developer machines where it regularly blow away and rebuild their database and also on deployed environment where we will only be adding new changesets.
When this program first runs on a deployed environment I need to detect if Liquibase has run or not and then run changelogSync to sync with the existing tables.
Other than manually checking if the database changelog table exists is there a way for the Liquibase API to let me know that it has already run at least once?
I'm using the Java core library in Groovy
The easiest way is probably ((StandardChangeLogHistoryService) ChangeLogHistoryServiceFactory.getInstance().getChangeLogService(database)).hasDatabaseChangeLogTable()
The ChangeLogHistoryService interface returned by liquibase.changelog.ChangeLogHistoryServiceFactory doesn't have a method to check if the table exists, but the StandardChangeLogHistoryService implementation does.

Using Liquibase and cherry-picking changesets

So I want to use liquibase as a replacement for SQL scripts for preparing databases in different development environment (SIT->UAT->PROD). The plan is to execute the liquibase update (with some other parameters in place if necessary), before start doing the testing.
The caveat is, all files (including liquibase XML) that are to be submitted to UAT and PROD must have been frozen; i.e. there could be no change for any files that has successfully passed SIT. Is there any way I can do this, so that in UAT I can only execute changesets which have successfully passed SIT (and similarly, in PROD I can only execute changesets which have successfully passed UAT), without actually altering the XML file on liquibase?
Thanks.
UPDATE
There are several issues which are inherent inside the current development cycle:
It would be redundant to ask the developers to run SIT again, this time with context=SIT being put inside.
Developer(s) only wanting to test their own changesets in the UAT. So a developer is only responsible for his own changesets; meaning they don't want to run others' changesets, even if these changesets have successfully passed SIT. Same issue also applies for UAT -> PROD.
Sorry I was not clear on this issue beforehand. I was tasked to implement Liquibase on my current workplace, and I don't have a really good picture of what's really happening in the cycle.
Liquibase does not allow you to pick certain changeSets to execute. The main reason for this is because the order that changes run against a database can make a big difference. Normally it doesn't help to have developers run just their changeSets because the database changes created by others are still needed by the application.
I think the most common way to handle your scenario is to rely on the same version control practices you use for your codebase. Liquibase is designed as a simple text format so that the changelog files can be stored in version control along with your code. Then, you can have branches for UAT and PROD and you can control what is going into those branches, including what changeSets are in the changelogs.
I think the best option wouuld be to use contexts (http://www.liquibase.org/documentation/contexts.html). ChangeSets that have passed SIT can be marked as context="sit". Then when you update UAT and PROD run with context=sit and only the tagged changesets will execute.
I think that based on your valid requirements that all scripts have to be frozen in the file-based version control which is external to Liquibase you have a major challenge here.
Liquibase cannot guarantee that files are frozen - it is not for Liquibase to know that.
You are welcome to review DBmaestro Teamwork, which enables you an enforced version control on your database objects (which guarantees that the repository and workspace database are in sync). Also generating the delta scripts handles all the merges (between different environments, UAT critical fixes, branches) from changes not originating from the development env.
Disclaimer -I'm working at DBmaestro

Rails, Git and adding migrations

sometimes when working in rails, I work on several things at once using git branches
sometimes, I'd like to test new ideas by implementing them and testing how and if they work accordingly. This involves sometimes adding models and migrations.
When switching branches, however, the migrations were already migrated to the DB and they stay, causing problems later on..
Is there a way to work with several branches and each to have different migration files, and before starting to work on a branch to "soft reset" the db only to the current migration files without losing data?
Normally, in development, I need some sample data that I keep in seed.rb which enables me to recreate the db, its structure and the sample data with a rake task.
Another thing I did was to keep more than one database. I would then just manually change the entry in database.yml according to the current git branch.