Packaging and reusing configuration in Drupal 8
Bringing "reusable features" to Drupal 8.
This is a preview of Nuvole's training at DrupalCon Amsterdam: An Effective Development Workflow in Drupal 8.
Configuration Management in Drupal 8 elegantly solves staging configuration between different environments addressing an issue that is still haunting even the most experienced Drupal 7 developer. In earlier posts we covered the new Configuration Management in Drupal 8, seeing how it compares to Drupal 7 and Features, and even investigated how to manually simulate Features in Drupal 8 last year. Recent developments and contrib modules can take us several steps closer.
Configuration Management can get quite streamlined when using Git and Drush 7 as explained below.
Step 1: Move staging configuration directory into a versionable location
By default Drupal 8 will place the staging directory under sites/default/files
and it is considered a good practice to not version that location, but an alternative location can easily be specified in our settings.php
:
<span style="color: #000000"><span style="color: #0000BB"><?php<br>$config_directories</span><span style="color: #007700">[</span><span style="color: #DD0000">'staging'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'config/staging'</span><span style="color: #007700">;<br></span><span style="color: #0000BB">?></span></span>
Done that, we must rebuild the Drupal cache:
$ drush cache-rebuild
Step 2: Export active configuration into staging directory via Drush
The Configuration Management system exposes a set of very handy Drush commands: in order to “dump” all active configuration into our newly set staging directory we can just run:
$ drush config-export<br>The current contents of your export directory (config/staging) will be deleted. (y/n): y<br>Configuration successfully exported to config/staging.
Step 3: Push configuration changes and import it on the staging environment
Since the staging directory is under version control we can simply git-add all its content and push it to the remote repository. After having set-up the staging environment as an exact replica of our development environment (this is actually required for the configuration staging to work) we can start profiting from the new Drupal 8 CM system. Imagine we have changed the site name on dev, after having exported, committed and pushed that change, on the staging site we will simply run:
$ git pull<br><br>$ drush config-import<br><br>Config Operation <br>system.site update<br>Import the listed configuration changes? (y/n): y<br>The configuration was imported successfully.
For a more comprehensive overview of the Configuration Management system please refer to our previous blog post Configuration Management: Drupal 7 to Drupal 8.
Packaging configuration
For those developers familiar with code-driven development practices the three steps above might resemble what the Features module does in Drupal 7 with its features-update
and features-revert
Drush commands.
While Drupal 8 configuration staging capabilities are far more advanced than what Features could possibly provide, what the new Configuration Management system really lacks is the ability to package configuration.
Enter the Configuration development module
The Configuration development module, currently maintained by chx, serves two main purposes:
- It automates the import of specified configuration files into the active storage.
- It automates the export of specified configuration objects into files.
The module offers a simple, global UI interface where a Drupal developer can set which configuration is automatically exported and imported any time they hit the “Save” button on a configuration setting page.
In order to achieve a more modular configuration packaging it would be enough to set a specific module’s config/install
directory as the actual export destination.
Nuvole contributed a patch to make that possible: instead of firing an auto-export every time a “Save” button is clicked the developer can, instead, specify in the module’s info file which configuration needs to be written back to that module’s install directory and run a simple Drush command to do that.
Reusable “features” in Drupal 8
One of the main advantages of having a standardized way of dealing with configuration means that modules can now stage configuration at installation time. In a way that’s something very close to what Features allowed us to do in Drupal 7.
Say we have our news section up and running on the site we are currently working on and we would like to package it into a custom module, together with some other custom code, and ship it over a new project. The patched Config development module will help us to do just that! Here it is how:
Step 1: Download, patch and enable Configuration development module
We need to download and enable the Configuration development module version 8.x-1.x-dev and apply the patch attached to this Drupal.org issue.
After rebuilding the cache, we will have the config-writeback
Drush command available. Let's have a closer look at what it is meant to do:
$ drush help config-writeback<br><br>Write back configuration to a module's config/install directory. State which configuration settings you want to export in the module's info file by listing them under 'config_devel', as shown below:<br><br>config_devel:<br> - entity.view_display.node.article.default<br> - entity.view_display.node.article.teaser<br> - field.instance.node.article.body<br><br><br>Examples:<br> drush config-writeback MODULE_NAME Write back configuration to the specified module, based on .info file.<br><br>Arguments:<br> module Module machine name.<br><br>Aliases: cwb
Step 2: Find what configuration needs to be packaged
We now look for all configuration related to our site’s news section. In Drupal 8 most of the site configuration is namespaced with related components so, if we keep on using consistent naming conventions, we can easily list all news-related configuration by simply running:
$ drush config-list | grep news<br><br>entity.form_display.node.news.default<br>entity.view_display.node.news.default<br>entity.view_display.node.news.teaser<br>field.instance.node.news.body<br>image.style.news_medium<br>menu.entity.node.news<br>node.type.news
Step 3: Package configuration
To package all the settings above we will create a module called custom_news
and, in its info file, we will specify all the settings we want to export, listing them under the config_devel:
directive, as follows:
$ cat modules/custom_news/custom_news.info.yml <br><br>name: Custom News<br>type: module<br>description: 'Custom news module.'<br>package: Custom<br>core: 8.x<br>config_devel:<br> - entity.form_display.node.news.default<br> - entity.view_display.node.news.default<br> - entity.view_display.node.news.teaser<br> - field.instance.node.news.body<br> - image.style.news_medium<br> - menu.entity.node.news<br> - node.type.news
After enabling the module we will run:
$ drush config-writeback custom_news
And we will have all our settings exported into the module’s install directory:
$ tree -L 3 modules/custom_news/<br><br>modules/custom_news/<br>├── config<br>│ └── install<br>│ ├── entity.view_display.node.news.default.yml<br>│ ├── entity.view_display.node.news.teaser.yml<br>│ ├── field.instance.node.news.body.yml<br>│ ├── image.style.news_medium.yml<br>│ ├── menu.entity.node.news.yml<br>│ └── node.type.news.yml<br>└── custom_news.info.yml
The Drush command above takes care of clearing all sensitive UUID values making sure that the module will stage the exported configuration cleanly, once enabled on a new Drupal 8 site.
To get the news section on another site we will just copy the module to the new site's ./modules/
directory and enable it:
$ drush en custom_news<br><br>The following extensions will be enabled: custom_news<br>Do you really want to continue? (y/n): y<br>custom_news was enabled successfully.
Final evaluation: Drupal 7 versus Drupal 8
One of the main differences between working in Drupal 7 and in Drupal 8 is represented by the new Configuration Management system.
While Features was proposing a one-stop solution for both configuration staging and packaging, Drupal 8 CM does a better job in keeping them separate, allowing developers in taking a greater control over these two different and, at the same time, complementary aspect of a solid Drupal development workflow.
By using the method described above we can upgrade our comparison table between Drupal 7 and Drupal 8 introduced in one of our previous posts as follows:
Functionality
D7 Core
D7 Core + Features
D8 Core (current)
D8 Core (current) + Patched Config Devel
Export full site config (no content)
NO
NO
YES
YES
Export selected config items
NO
YES
YES
YES
Track config changes (full site)
NO
NO
YES
YES
Track config changes (selected items)
NO
YES
YES
YES
Stage configuration
NO
YES
YES
YES
Package configuration
NO
YES
NO
YES
Reuse configuration in other projects
NO
YES
NO
YES
Collaborate on the same project
NO
YES
NO
NO
The last "NO" deserves a brief explanation: Configuration Management allows two developers to work simultaneously on different parts of the same project if they are very careful: but "merging" the work would have to be done by version control (GIT or similar), that doesn't know about YAML or Drupal.
Some open issues
Contributed modules seem to be the best way to enhance the core Configuration Management system, much like what happened with Drupal 7 and Features. There are still several issues that should be considered for an optimal workflow, to match and improve what we already have in Drupal 7:
- Piping: the ability to relate configuration components based on both hard and logic dependencies, for example: I export a content type and, automatically, I get also its fields. If piping might have been too rigid, at times, it would be still useful to have in some configurable form.
- Enhanced configuration diff: it might be useful to have the possibility to review what configuration is going to be installed before enabling a module, like it is now when importing staged configuration to the active storage.
- Granularity: it is still impossible to export part of a configuration file, so we still depend on the core conventions for grouping configuration into files, and we can't export a single permission for example.
- Ownership: we can't know if another module (or "feature") is tracking a component we wish to track; this could be useful in the perspective of maintaining several "modular" features.
- Updates: we can reuse configuration by simply enabling a module, but this holds only for the initial installation; after a module is enabled, we don't have a clean way to import changes (say, to "upgrade" to a newer version of the feature) outside the standard workflow foreseen in Configuration Management.
Tags: Drupal 8, Drupal Planet, DrupalCon, Drush, Code Driven DevelopmentImage: