Features - Structured and Organised Site Building

Deploying a new Drupal site is generally not a big problem, especially if it is a small site with not to many complicated features. An easy way is to simply use the Backup and Migrate module, take a backup of the database, upload the whole site repository and then restore the database and job done.

However, when you later want to add new features, the problems start to mount up. You need to really test things before you start making changes on the live site and at the same time document everything to create a step-by-step guide on how to make the new feature live. Depending on how much is involved, this could mean that you need to have the live site in maintenance mode for quite some time.

The problems with deploying changes or new features to existing sites stems from that everything is stored in the database, both content and configuration. Adding to it is that there is no easy way to know what is content and what is configuration, with the sole exception being the variables table. Until Drupal 8 and the Configurations Management initiative, lead by Greg Dunlap (heyrocker), is available this is going to remain being a pain for us.

There exists many ideas, solutions and modules for making this more streamlined, one such method is using the Features module, which is the method I am focusing on in this post.

What is the Features module?

From the project page on drupal.org:

The features module enables the capture and management of features in Drupal. A feature is a collection of Drupal entities which taken together satisfy a certain use-case.

Features provides a UI and API for taking different site building components from modules with exportables and bundling them together in a single feature module.

Simply speaking, Features let you collect configurations for both Drupal Core and contributed modules and export them to code in a module that can be installed like any other module on the live site. Even better, it also provides an UI where you can manage all your Features modules.

Benefits this includes are:

  • Integrates with the CTools export API which enables configuration export from many modules, including Views, Panels, Context, etc.
  • Supports Strongarm to allow you to export configurations from the variables table.
  • Configuration in code.
  • Possibility to add custom code to each feature module created.
  • Version control management of configurations.
  • Much easier and quicker to deploy updated/new features.

This all sounds fantastic, and to much degree it is really making things much easier. Unfortunately it is not the complete solution you may think it is at first glance. Below I will go over how it works today, as well as what is really important to have in mind when using it.

Planning Ahead

Before you start creating your features it is important that you understand a few concepts and restrictions. Especially important to understand is that features doesn't fix the underlying problems with that configuration and content is mashed together in the database, it only tries to do the best it can of a bad situation. Also, not all configuration is possible to export with it, it depends on how it is stored and whether needed support in a contributed module exists or not.

Therefor you need to carefully plan ahead before starting to create your features. A couple of rules I have created for my features are:

  1. Separate site features into separate features modules that can be maintained individually.
  2. Avoid adding configurations that are likely to be changed on the live site.
  3. Document everything, especially what is in the features and what other steps are necessary when deploying them.

It would be easy to mash all settings for a site into one gigantic features module, but the result will only be that maintaining it will be more and more difficult. Instead, try and make each module focused on a particular feature on the site, such as the Contact Form or the Image Gallery. That will not only make them easier to maintain, it will also make them reusable for other sites.

For my site projects I usually have one Foundation feature module. Its purpose is to enable all the basic, not feature specific, modules needed on the site as well as contain all the static settings for them. With static settings I mean those that are very unlikely to change on the live site.

Then I will create a bunch of other feature modules that are focused on specific features or sections of the site. I will avoid adding configurations to a feature module that are also going to be needed for other features. For example Image Styles, those will be used by many different features, therefor they will have their own module.

While developing my features I am also documenting everything. Each feature will have its own document where I list all dependencies as well as other steps necessary when deploying the feature on a live site. Then I will also have an overall site administration document. It will both list all features the site is utilising, as well as what settings that are free to change and all other administration tasks on the live site.

Then, before deploying a new, or updated, features module, I always test it on a staging site containing a copy of the live sit. During these test I also go over my documentation and write a step by step guide on how to deploy, including any other changes needed.

Doing it this way has helped to both make development of sites easier, but more importantly given me a much more flexible and easy way of deploying changes on the live site. It has also resulted in that the sites are easier to maintain and administrate, not only by myself, but also for any other site administrator.

Companion Modules

As described above, the Strongarm module allow you to add configurations from the variables table to your features. Not using it would restrict your possibilities so I recommend you use it.

Another very useful module to add is Diff. It is especially useful on the live site. There is nothing that prevents you from overriding a setting from a feature module, which will happen at some stage. With the Diff module installed, the Features admin page will list those features as having overridden settings and also let you view what those changes are. It is extremely handy to have so I strongly suggest you instal it too.

Very Important Oddities!

Before I end this post I would like to share some very important oddities I have noticed while working with this module. It is important that you understand these and make sure that you follow my suggestions for how to avoid getting into problems, or in worst case render the live site unusable.

Updates to existing enabled features will be automatically applied!
As soon as any page on the live site is fetched, Features will apply the new settings without asking.

This can cause all sort of problems if your not careful. Especially if the update adds dependencies on modules that the old version didn't have and that was not installed before you uploaded the new features version. In worst case your site will be rendered useless and create extra work for you to fix this.

Make sure that you first upload any new modules that the feature needs!

Disabling a feature might remove some settings!
Since features can be disabled, Features tries to also remove its settings. This to can have unwanted results if your not careful.

My best advice here is that you test what happens when you disable a feature on a copy of the live site.

Features with only dependencies does not show up on the Features admin page!
You will rarely create a feature module that only enables a bunch of modules, but its good to keep this oddity in mind if your new feature isn't showing up on the admin page after you upload it.

I have filed some issue tickets about these oddities and hopefully future versions will be improved to sort them out.

Conclusion

Using the Features module has not only helped me to both better structure my development process and deployment of features on live sites. It has also made me better understand how Drupal works, where stuff are stored and better plan new development. As a bonus the end result has been sites that are both easier to further improve and administrate.

Features does not solve the underlying problems with having configuration and settings mashed together in the database, but it does give us much better control over it. Until Drupal 8 and the complete separation of content and configuration is in place, this is one of the best solutions we have.

Of course, the way I am using Features is just one way, I'm sure many of you use it differently. Therefore it would be interesting to know more about your experiences using it. Feel free to share your experience in the comments below, I'm looking forward to hear about them.

Resources

Comments

Patrick Connolly's picture

Thanks for the article! A little confused by this line:

<blockquote>Updates to existing enabled features will be automatically applied!</blockquote>

How do you mean? It sounds like you're saying that features will automatically revert the site settings to match those that are in code on each pageload, but I'm almost certain that this isn't the case. Could it be that you're just talking about "Dependency" feature components? I haven't checked, but if these simply add a "dependency[]" directive to the myfeature.info file, then yeah, INFO files are loaded with bootstrap and your site might kablooey if anything is missing. But otherwise, that sentence may be a bit misleading.

Anyhow, thanks again for this! We're working with features now too, and it's reassuring to hear that we've taken similar lessons from it :)

tsvenson's picture

Hi Patrick,

As I explain under the bold text this applies to new settings when updating an existing feature. You can test this easily by simply adding something new to an existing feature (that will show up on pages), upload it and then load that page. The new item will be there without you having to go to the admin and trigger feature to apply them.

As far as I have seen so far, it wont overwrite changes to items that existed in the old version, except module dependencies. Those will be highlighted as overridden.

This is not a big problem as long as you are aware of it. Personally though I don't like this. I would prefer if Features don't apply updates until I manually trigger them.

In a perfect world it would let me:

  1. Select all updates (several features modules)
  2. Optionally put the site in maintenance mode
  3. Apply the updates
  4. Put the site back in live mode

This would be very useful when you have updates to several features modules that also contain dependencies on each other.

Patrick Connolly's picture

I'm with you on that seeming a bit of an odd approach. Just wanted to say thanks for setting me straight Thomas :)

tsvenson's picture

Your welcome, glad I could help. I have also, thanks to your comment, updated my initial issue on d.o with a suggestion to add functionality as I outlined in my previous comment.

Fabian Franz's picture

Hi Thomas,

While your approach seems valid and well thought, it is not. Rather you need to re-think your deployment strategy if you want to use features. Because you have overlooked one thing:

Features _do_ live in code. (which saves a DB Hit)

Consider the following scenario:

You are adding a view to your frontpage, which is for example just using date and content. But now you add views_customfield to the mix. The feature does detect the dependency and auto-adds it to your feature.

What you are now proposing is:

You deploy the code, now the old view is used, then you approve the change, then the new code is used.

But as soon as you upload the new feature the new code will be in place and it will expect views_customfield (or whatever other module you added) to be present.

Basically: The uploading of the feature _is_ the authorization of these changes. Only if you have changed variants on your production, will you need to actually revert or re-authorize.

However this again is a workflow issue and not an issue of features, because you should always update over a clean state as you don't want to override production changes, or do you?

Here is how to use a proper workflow using git branches:

We have three branches:

dev, staging and production

1. First you update your production branch with any changes you have on the server and also update all features.
( at least if you only did _wanted_ changes on production)

2. You review those changes. You commit those changes you want to the production branch and revert the others.

3. You revert all features. - Now you have a clean state again on your production and all features run from code.

4. You export your staged changes also into features. (if they not yet live in code anyway).

5. You merge production into staging.

6. You review all the changes and solve possible conflicts. (in code)

7. Now your staging environment is up to date.

8. Now you test everything and merge staging into production and tag it as production-v.1.3

9. And now you deploy your feature to your production system by fetching the changes and checking out the new tag by doing (with git):

$ drush vset -y site_offline 1
$ git checkout production-v1.3 # tested and all deps present
$ drush updb # update DB
$ drush features # check the status and possibly revert (even though this _should_ not be possible)
$ drush vset -y site_offline 0

And then you have deployed the code from staging to production.

The advantage of features is that the changes live in code, so you need to make sure your deployment is code based.

And you'll always have the same problem with dependencies (also for custom modules). If you add dependencies the present module will be updated to need them, but it may not be present and that can break your site, too.

Features == Change Deployment from manual DB changes to Code Deployment

And then you'll need to work with a structure that allows safe code deployments.

But you understood features to be like:

"I have code in DB and I can export them to features and re-import them to the DB. And I can choose, which thigns to import or export after having deployed the feature."

Features won't do this. Briefcase module can do this (for example).

Features _allows_ you to override things and such bridges a gap between the classical everything needss to live in code, but then also needs to be changed via code and I do all changes graphically.

People did use code based workflows even before features module, but it was much more complicated back then.

Anyway, I hope this helps to clarify why Features itself are not a double edged sword, but the way you use it is.

Best Wishes,

Fabian

Fabian Franz's picture

For those confused, that comment was supposed to go to:

http://www.drupalmill.com/blog/tsvenson/2011/06/03/features-module-double-edged-sword

Sorry for that.

Best Wishes,

Fabian

Add new comment