How to import config without losing changes
James Williams
Drupal empowers site builders and editors to configure their sites in settings forms. Configuration management lets developers push changes up to live sites to be imported. But developers have to be considerate to ensure imports will not wipe out those changes made directly through the live sites' settings forms. At the least, they have to export the changes before making further tweaks. But admins may make further changes in the meantime too, so developers can end up frequently pulling irrelevant changes back from live, which seems unnecessary.
Here's some examples of the kind of config that I'm thinking of:
- The site email and Google Analytics account are usually managed by site admins, not developers. So developers should not be the ones to manage those settings.
- Marketers may like tweaking the site name or slogan. That doesn't need to affect developers.
- Contact forms contain labels and other text which may be key to the communication between a client and their customers.
- Permissions - sometimes it's not clear where the lines are between editors/admins/etc, so why not allow some flexibility to reassign permissions directly on live without needing to touch the codebase?
We need an approach that allows for specific settings to be considered 'unmanaged' - so an import wouldn't touch whatever they have made to be on live. The Config Ignore project claims to solve this, but we already use Config split which is more powerful, more flexible and has a better user interface. (Although Config Ignore does allow targeting parts of config rather than whole config items.)
Config split is often used to create environment-specific sets of configuration, but its design means it can be used for separating config for other purposes. In this scenario, what's needed is a split that represents settings to be protected, which can be exported immediately before any import. Then when importing, Drupal only sees the preserved version of the settings, so won't change them, regardless of what is in the main configuration files.
The split, which I've called 'Unmanaged', needs to be set up like as follows (see screenshot):
- Use a folder (directory) which already exists and is writable. I use
../config/unmanaged
, so it matches the split name and is outside the webroot. - Set to active. I usually set all other splits to inactive, and only make them active in an environment's
settings.php
, but this split exists for the sake of workflow, not environment. For example, it can actually be useful locally, so I can tweak things for development without affecting what ends up in version control. - Have the largest weight of any split, so that it overrides any other exported version of config it contains.
- Use the Conditional split section, not Complete split, to pick configuration to protect.
- Do not tick either of the checkboxes in the conditional split section.
Once the split has been created, the container needs rebuilding for it to work. Run this, which includes exporting it for the first time:
drush cache-rebuild
drush -y config-split-export unmanaged
Now that it is exported, a .htaccess
file will be have been added to the directory alongside the config. Add the following line to your project's .gitignore
file, adjusting the directory location as appropriate. This ensures the directory will get created on live when changes are pulled from git (containing .htaccess
), but deliberately without the exported config:
config/unmanaged/*.yml
So now before running any imports, make sure to export the split:
drush -y config-split-export unmanaged
drush -y config-import
With this split and the export step in place in your workflow, you can be confident of allowing your developers and site admins to get on with their respective work, without getting in each others' way. This puts configuration splits to use for something beyond environment-specific overrides, which I think is exciting. I wonder what other useful purposes they may have?
Photo by Sascha Hormel from Pexels