Why are all contexts executed when non specified on update?

13.6k views Asked by At

I'm using Liquibase 3.3.5 to update my database. Having contexts is a nice way to only execute specific parts of the changelog. But I don't understand, why ALL changesets are executed, when no context is provided on update. Consider the following example:

  • changeset A: context=test
  • changeset B: no context
  • changeset C: context=prod

So

  • executing update with context=test, will execute changeset A+B.
  • executing update with context=prod, will execute changeset B+C.
  • executing update with no context, will execute changeset A+B+C.

For me, this doesn't make sense at all :).

I would expect, that only changeset B will be executed, since it doesn't define a specific context.

In the Liquibase contexts example: http://www.liquibase.org/documentation/contexts.html ("Using Contexts for Test Data") they say, that one should mark the changesets for testing with "test", and executing them with giving the context "test" to apply testdata. Fine - make sense. But

"When it comes time to migrate your production database, don’t include the “test" context, and your test data not be included. "

So, if I wouldn't specify "test" context when executing production update, it would execute the "test" changesets as well, since I didn't specify a context at all.

Again, I would expect that leaving out test on update execution, would only perform the regular changesets without the test changesets.

Or I'm missing something here :)?

5

There are 5 answers

4
SteveDonie On BEST ANSWER

This is just how Liquibase works - if you do an update and don't specify a context, then all changesets are considered as applicable to that update operation.

There were a couple of ways that this could have been implemented, and the development team had to pick one.

  1. if you don't specify a context during an update operation, then no changesets are considered.
  2. if you don't specify a context, then all changesets are considered.
  3. if you don't specify a context, then only changesets that have no context are considered.
  4. if you don't specify a context and none of the changesets have contexts on them, then all changesets are considered, but if some of the changesets do have contexts, go to option 1, 2, or 3 above.

The team could have gone with option 3 (which matches your expectation) but decided long ago to go with option 2, as that seemed like the 'best' way at the time. I wasn't on the team at that time, so I don't know any more than that.

0
Taoufik Mohdit On

It might be too late for @javg, but this may benefit future readers. This requirement could be achieved as follows:

changeset A: context=test
changeset B: context=all
changeset C: context=prod

So

executing update with "context=test,all" will execute changeset A+B.
executing update with "context=all,prod" will execute changeset B+C.
executing update with "context=all" will only execute changeset B as you expect.
0
Johnathan J. On

I just mark the development changeSets as "dev" [or "test"] and don't specify a context on the changesets that run in both. When I do an update on production, I will specify contexts=prod in the update even though there are no changesets marked as prod. That will make it skip all the dev [or "test"] context ones but will still execute all the non-context-ed changeSets. You are also then set up for some point in the future where you need to make a context="prod" changeSet that ... only runs in prod.

Source: https://forum.liquibase.org/t/using-context-for-development-only-and-production-changesets/980/2

0
dsuchka On

And what happens if you or your admin forgets to specify a context? Yes, it will execute A+B+C, on a production it can break many of things and make your life not so happy.

I'm looking for a solution that benefits in these cases and aborts the liquibase execution at the beginning (when you are running liquibase without any contexts).

It would be cool if the liquibase has a property (in liquibase.properties) to restrict running with/without contexts...

As an solution you can add contexts=default,contexts,of,your,project to the liquibase.properties file.

0
Przemek Nowak On

I will add solution from me (from my perspective the default Liquibase behavior is not intuitive). In our project to deal with the "problem" we configured liquibase context in this way:

liquibase.setChangeLog("classpath*:liquibase/master.xml");
contexts = StringUtils.isBlank(contexts) ? "none" : contexts;
liquibase.setContexts(contexts);

It cause that liquibase will run all change-sets with context 'none' and all default change-sets (change-sets without context) - yes this is how it works.

So select the name which nobody on your team won't use ('none' in our case) as context name and then run the liquibase by default with that context (take a look at example). With that approach you will run the change-sets without any context what I assume should be default approach!