Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
A typical workflow is that developers, on a local version of a site, will update the code, then run:
...
drush updb
drush cim
...
The important thing here is that drush updb is often run before drush cim, and this is the suggested course of action proposed, for example, in:
- This comment on the config-split issue "Dependancy on non-existent service"
- Order of Drush commands for automated deployment, Stack Exchange
Where this will fail however when drush updb updates configuration, as happens, for example, when:
We realize, thus, that whatever order we run drush cim, drush updb, and drush cex in, none is foolproof:
This will fail, for example, in the scenario described here:
drush cim
drush updb
This will fail, for example, in the scenario described here
drush updb
drush cim
Possible resolutions
- Better documentation?
- A combined updb/cim command?
- Warning that drush cex should be run in case config is deemed out-of-date in code?
Comments
Comment #2
alberto56 CreditAttribution: alberto56 at Dcycle commentedThis title better reflects what I am trying to convey with this issue.
Comment #3
xjmSince we would presumably fix this in D8 too, I'm filing it against 8.8.x (which is the current bugfix support branch). Patches can be tested against other branches as needed when they're uploaded without changing the issue's version selector.
The issue will be automatically updated to 8.9.x after the last 8.8.x bugfix release. Thanks!
Comment #5
DakwamineAs a developer, it would be interesting that updb do the following:
On top of this, a --deployment or --no-config-check flag could be added for scenarios when checking the configs are unnecessary (or maybe reuse the -y flag?).
The only unsupported scenario is when the update is triggered in the UI (update.php). A similar functionality has to be implemented in the update.php: UI to show the config diff, ask to run the update, show the diff again to warn the config changes.
Could this be enough to help with avoiding CMI mistakes? This has the advantage that the update functionality itself is not modified, it only asks for confirmation and warns.
Comment #6
bircherI am adding two related issues:
#2762235: Ensure that ConfigImport is taking place without outstanding updates This will effectively enforce the order of operations (ie you can not
cim
beforeupdb
)#3046903: [discussion] Environment specific modules with updates. This seems unrelated at first but will maybe be needing a similar approach than what #5 is suggesting.
Worth noting is also the drush deploy command.
Comment #7
moshe weitzman CreditAttribution: moshe weitzman commentedIMO this is not a supported workflow. You *must* get your configuration right before you run a config import. Specifically, the config in the import must represent the values AFTER hook_updated_n runs. The developer workflow I advocate is to run the hook_update_n() locally, run drush config:export, and and then commit the results. Only then is the saved config ready to be imported.
I'm sure docs could be improved in this area.
Comment #8
a.dmitriiev CreditAttribution: a.dmitriiev as a volunteer and at 1xINTERNET commented@moshe weitzman, what about the fields? If the fields storage and field instance was created in update/post_update hook and then exported locally to config/sync with some uuid, then on remote server the uuid might be different and then the field will be re-created on configuration import. If there is any post_update that migrates some data to those fields, that data will be lost, because config import will delete the field and create it again.
Comment #9
moshe weitzman CreditAttribution: moshe weitzman commentedContent should be entered via a HOOK_deploy_NAME(). Thats a new hook introduced by the drush deploy command. See https://www.drush.org/deploycommand/
Also, you don't need hook_update_n() to propagate a field creation. Do it locally in the GUI, and then config:export and the commit the result. No more is needed. Or just use base fields which are all in code.
Comment #10
a.dmitriiev CreditAttribution: a.dmitriiev as a volunteer and at 1xINTERNET commentedThanks, but that deploy hook is only available with Drush 10, or? and the update hook I use to create commerce_subscription field, there is no UI for that.
Comment #11
moshe weitzman CreditAttribution: moshe weitzman commentedCorrect on Drush 10. Ideally core would have that hook but it doesnt yet acknowledge that drupal deployment is a thing.
Comment #12
alberto56 CreditAttribution: alberto56 at Dcycle commentedThis is reasonable, but there is still another case where configuration changes made by hook_update_N() are not reflected. Consider the following scenario:
* a site development team overrides configuration in the settings.php file, but only on production. Concretely, maybe they have webform 5.x and override the webform.settings.default_page_base_path (which is "form" by default) and change it to "forms", but in settings.php, not in the database or in the site's config files.
* webform 6.x comes out, and in an update hook, updates "webform.settings.default_page_base_path" so that it is prepended with a slash, "/forms". In fact all forms completely break if this update is not performed.
* the developers run drush updb, make sure to commit the resulting changes to the config ("get your configuration right"), and push to production, and run drush updb && drush cim there.
At this point all forms stop working on production because config is overridden in settings.php using an "old" way of doing things, and the reason is not immediately clear.
A solution might be strongly advise module developers to avoid modifying configuration in update hooks, and, if they do, to implement hook_requirements() to make sure the changes are, in fact, reflected.
I wrote more about this in a blog post at https://blog.dcycle.com/blog/2021-01-29/hook_update_n/
Comment #17
markdorisonThis issue recently affected us with the release of Drupal 10.1. #1845004: Replace custom password hashing library with PHP password_hash() included an update hook to enable the new
phpass
core module. Once that update hook ran, the module was enabled only to be disabled whenconfig:import
was subsequently run.We have automated tests that check the status of Drupal config state, but these did not fail because once
config:import
had run (viadrush deploy
), the configuration on disk matched the active configuration as far as Drupal was concerned.If we are allowing folks to believe that configuration on disk is their source of truth and then modifying active configuration with an update hook, this seems like it will inevitably cause issues like this.
Comment #18
gcbIt seems to me like there's a fundamental contradiction to running database updates and configuration updates all in a single action.
It's already very complicated to wrestle with the concept of "correct configuration" when you have site administrators making configuration updates and developers making configuration updates in parallel.
What if configuration updates in code were given special treatment? We could have a separate one-time operation from updb [hook_install_configuration_N(): returns an array of configuration files to be re-imported from a module's /config/*/ directories; is triggered by 'drush update-configuration' or visiting /update-config.php]
Then, the "best practice" could be:
1. updb
2. cim
3. upcfg
(and then: export that config into code!)
If we tracked the executed upcfg functions in their own table with a date or "invocation" column, we could provide a way to "re-run" an invocation if a site accidentally ran CIM after upcfg.
Comment #19
YesCT CreditAttribution: YesCT at Lullabot commentedAt Lullabot, we wrote up an Architecture Decision Record (ADR) to deal with a similar situation.
https://architecture.lullabot.com/adr/20210924-drupal-build-steps/
Depends on developers using hook_post_update_NAME() . [ 1845004 did use a hook_post_update_NAME: system_post_update_enable_password_compatibility ]
Oh, and that ADR works in conjunction with this one: https://architecture.lullabot.com/adr/20211212-config-status-check/
Does that help?
Comment #20
moshe weitzman CreditAttribution: moshe weitzman commentedA PR is in progress for drush deploy to catch this problem and stop the deployment - https://github.com/drush-ops/drush/pull/5713
Comment #21
Anybody