Simplify your WordPress Deployments

Deploying code to WordPress installations has always been a bit of a struggle. Although there are a few WordPress plugins that help in deployments, there hasn't really been a simple WordPress deployment process. It's about time that process became a lot easier.

Let's say we have four WordPress environments for a site we are working on: local, development, staging and production. Each of these environments would use separate databases, and would be accessible from different hostnames. For each of these environments we've got to be able to rollout code, synchronize the database and uploaded files. WordPress makes this slightly more difficult by storing absolute urls of its content in the database. At one of my previous jobs, we attempted to handle deployment of a WordPress site with a very long and confusing php script. It was very complex, contained all of the developers' individual environment details, and was certainly not the most eloquent solution.

Let's make deploying WordPress simple!

By using Capistrano, git, wp-cli and sed we can create a simplifed deployment process. Here's what it will do:

  • Set up additional environments by cap staging deploy:setup
  • Make deploying code to other environments a snap with cap staging deploy
  • Make pulling and pushing the database (and searching and replace those absolute urls) as easy as cap prod db:pull and cap dev db:push
  • Handle repository-ignored files (wp-content/uploads, etc) with cap prod files:pull and cap dev files:push

Sounds like a good idea, right? Let's take a look at how this is accomplished. First we've got to handle the wp-config.php file to be used on many environments. This is done by including a file, local-config.php, that will store the local environment's configuration, and is left out of the repository by .gitignore. Also ignored by .gitignore are your wp-content/uploads, wp-content/w3tc, wp-content/avatars, wp-content/cache etc. A directory I created called db/ is also ignored by git. That's where we'll store database dumps that we pulled from a different environment, or want to push to one.

The Capfile does the heavy lifting here. Some of the rails-specific tasks have been disabled here (migrate, migrations, cold, start, stop, restart) and we've added tasks for handling the setup, files, deploy and db. I'll save you the detail of going over the specifics of the capfile. If you are interested, I've provided a sample one you can download at the bottom of this blog post. Wp-CLI is a great tool that is bringing drush-like functionality to WordPress. I'm using it in this deployment strategy to handle database imports and exports on the capistrano targets.

One more area of note would be the config/deploy.rb file. This contains some settings you'd need to set before attempting to deploy anywhere.

When this is all set-up, your development workflow should look like something like: develop locally, commit and push to git, cap deploy to dev/staging, test there, cap deploy to production and ensure production works.

You can checkout what a sample repository would look like here. If you aren't familiar with capistrano and git, you might want to get used to them before attempting to use this codebase for your projects.

Comments

I browsed your github repo, more specifically with regards to the database export and import. I am wondering how you handle overwriting the production data.

For example, say I have develop locally and install a plugin locally that makes database changes. Now I want to deploy these changes to production, but I don't want to lose and comments or anything that may have been changed on the production database. How do you handle it? It seems as though looking in the cap recipes that you just export the dev db and import it, and overwrite the production database. Unless I'm missing something.

I would greatly appreciate your input and any direction that you can give me. Thanks again!

Best,
Jason

When you do make database changes that need to go from dev up to production, you'd want to do this via code. Write a plugin to do your database manipulation. In Wordpress you'd probably want to write a hook to check to see if your plugin has made the necessary db changes and make them if it hasn't already. In Drupal this is easily achieved by a module's update script. To re-iterate, you'd want to make any db changes via code -- so it is reproducible and deployable. Then, be sure to test the deployment to a staging environment (that has a fresh copy of the database/content from the production environment). Once testing is complete, deploy the code to production.

I totally agree that making changes to the db via code is the way to go, this way you can check on "that" file and run the "migration". The reason I'm thinking about this is for those instances where there's a WP site, but then some sort of custom code that has been written that sits outside of the WP install. With a custom PHP app, sometimes the aspects of the database are just done straight in MySQL. There may not be an answer to that scenario, but I was just curious as to your thoughts.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Ready for transformation?