“Hey Laurent, I just finished the support work for the website and I need you to deploy it. Here's a click-click file describing where you need to click in the Drupal admin interface to reproduce the fix on your dev environment, on staging and on prod.”
That's a situation every Drupal developer came accross at least once in his life: deployment nightmare. How can we maintain and deploy a website that has almost everything stored in its database? Some people use the “click-click in the admin until everything is fixed” method, while others directly fetch the source with an SCM software installed on the target server and apply database patches by hand. But let's think again about what “deploying” implies… A typical Drupal website:
- is a set of files to be deployed
- has some dependencies (Apache and PHP are some of them, or you might be using curl in your code so you'll need the php-curl extension)
- uses a database that needs to be updated along with the code
- uses some configuration depending on the instance (like database credentials)
All of these points can be automated using a well-known method: Debian packaging. Debian packages allow us to pack a set of files thus creating a package that will have other packages as dependencies and custom install scripts (like postinst). Also debconf allows us to easily configure a package. That's perfectly suited to our needs and gives us the following advantages:
- we can automatically backup the database before updating the site (also database management is done by dbconfig-common)
- we don't need to install software dependencies (eg. php modules) by hand
- we clearly know if the update went well or not (package in a broken state)
- we can easily reconfigure our package using dpkg-reconfigure (eg. if the IP address of our database server changed)
- we always know which version of the site is deployed
How do we package
A basic Debian package is quite easy to make: you create some files giving information about which files should go in the package, where they should be put, what packages your package depends on and what additional commands should be executed during the install process. You can also create a config file which will define the questions that should be asked when installing the package (in our case that will be the DB credentials, the install profile to use, the site name, etc).
Once your package is created you can scp it to your target server and install it using dpkg. Done!
I know you're wondering “there's no difference with a tar file, so why losing time creating a deb file? And you talked about database updates?”.
Features to the rescue
Drupal Features is a great module that allows you to do some click-click stuff on your dev machine and then export it as a module. That way, you'll be able to deploy your modifications without having to do any click-click stuff again and without having to worry about your database changes. You can export blocks, views, content types and even variables. Also it has a drush interface that allows you to revert a feature back into your database, which is just what we need for our deployment stuff.
Of course there are some things you won't be able to write with features, but you can still fall back to hook_update_N functions.
We now have nice modules that will update everything we need. We just need to call them in our deployment postinst file so they will be automatically applied after the deployment: “drush fra” will revert all our features back to the database and “drush updb” will take care of hook_update_N functions.
Packaging your Drupal site using Debian packages takes some time at the beginning because you have to write some scripts and understand how Debian packaging works. But once you've done that, you'll be able to deploy your website in a fully-automated way, without having to worry whether the update went well or not, because if your staging deployment worked, you know your prod deployment will too. Don't forget we have some nice scripts you can use to ease your deployment a little more.