How we fixed the perpetual hook_update_N merge conflict problem | Roomify

How we fixed the perpetual hook_update_N merge conflict problem

by
Adrian Rollett

If you work on a Drupal site with a development team, you've probably run into merge conflicts created by database updates using the same update number. (E.g. developer 1 creates custom_module_update_7013 in one branch, and developer 2 creates the same update function in another branch) Wouldn't it be nicer if updates used machine names instead, or indeed almost anything besides incremented integers? After many weeks of wasting time fixing spurious conflicts and slowing down our development process on Roomify for Accommodations, we decided to do something about it.

We've created a new module called better_db_updates - it solves the problem by allowing modules to place database updates in individual files. The module also provides a drush command to run all updates, including better DB updates. Usage is really simple, just require the better_db_updates module and implement hook_better_updates_db_directory():

/**
 * Implements hook_better_db_updates_directory()
 */
function test_better_db_updates_directory() {
  return 'updates';
}

To add a database update that changes your site name, add a file called update_site_name.inc in the updates directory under your module's directory:

<?php

/**
 * Update to the new site name
 */

variable_set('site_name', 'My Drupal Site');
 

That's all there is to it! We hope you'll check out the module and offer feedback.

Adrian Rollett
Adrian is a co-founder at Roomify - he usually is waist-deep working on our apps and infrastructure.

Comments

How does better_db_updates handle dependencies and how to select the running order?

Are those situations cases where hook_update_N() makes more sense than using better_db_updates?

because module_implements respects module weight, running order does as well.

That solves it between different modules, but what about updates contained within the same module? How are those ordered?

Good question! They are ordered as returned by file_scan_directory, which is not gauranteed to be consistent across different systems. We should explicitly sort by e.g. filename, I've added https://www.drupal.org/node/2766533

 

Additionally it could perhaps make sense to allow updates to explicitly require another update, perhaps with a @require tag in the docblock - any thoughts? Another option could be to have a yml file associated with each update file that could have the update's description string and specify any required updates...

I'm kind of liking the second option, it would remove the need to scan the update file for the update description...

We used drush_update_modules for that same task before :).

We found that modules have the advantage of having dependencies and as such updates can be ordered more easily.

We also wrote a BC layer to convert back update_modules to regular updates.

https://www.drupal.org/project/drush_update_modules

If you also have much features merge conflicts, you might consider to give cmk (https://www.drupal.org/project/cmk) module a try, which uses one file per export.

Compared to features always a true revert is needed however as there are no rebuilds.

It was made for a big enterprise client :).

Thanks,

Fabian

cool to see another solution, thanks for posting! We haven't run into the issue of needing to order updates but that's nice to keep in mind if we do. (and module weight can't be set accordingly)