This post is the second in a series of deployment workflows I use to get code into production.
The site you’re reading this on is often a neglected playground of sorts. I’ll run into an interesting method of provisioning the server or maintaining code, apply it halfway and then get distracted with something else.
Hearting my new Fabric deploy scripts. Hearting.
— Jeremy Felt (@jeremyfelt) September 10, 2013
That said, somewhere around 16 months ago, I tried out Fabric to manage deployment actions for individual sites and decided to stick with it.
A fair warning is in order—I found an immediate, quick way to use Fabric to accomplish a handful of tasks and then let it be. It’s likely much more powerful than a wrapper for
rsync, but that’s basically how I’m using it.
Ok. Backing up a bit, I think this workflow makes the most sense when you look at how the code is arranged.
www/is where WordPress and its config files live.
www/wordpressis a submodule pointed at
core.git.wordpress.orgso that I can run trunk or a specific branch.
tweets/is a submodule pointed at
https://github.com/jeremyfelt/tweets.jeremyfelt.com, where I maintain a version controlled copy of my Twitter archive.
The arrangement goes along with the types of code involved:
- (wp-config, mu-plugins) Code custom or very specific to jeremyfelt.com. This should exist in the repository.
- (plugins, themes) Code that cannot be sanely managed with submodules AND that I want to manage through the WordPress admin. This should exist in the repository.
- (WordPress, tweets) Code part of sanely available repositories that can be used as submodules.
Anything in a submodule is really only necessary in the working directory we’re deploying from, so the pain points I normally have with submodules go away. I think (assume?) that’s because this is the purpose of submodules. 😉
Ok, all the code is in its right place at this point.
With the fabfile.py file in my directory, I have access to several commands at the command line. Here are the ones I actually use:
fab pull_plugins– Pull any plugins from production into the local plugins directory. This allows me to use WordPress to manage my plugins in production while keeping them in some sort of version control.
fab pull_themes– Pull any themes from production into the local themes directory. Again, I can use WordPress to manage these in production.
fab pull_uploads– Pull my uploads directory from production to maintain a backup of all uploaded content.
fab sync_themes– When I update WordPress via git, this command is a nice shortcut to sync over any changes to the default theme(s).
fab push_www– Push any local changes in the www directory to production. This is primarily used for any changes to WordPress.
fab push_tweets– Push any local changes in the tweets directory to production. This effectively updates tweets.jeremyfelt.com.
fab push_content– Push any plugin and theme updates that I may have done locally to production. I don’t have to separate these actions because I already have them in version control, so I’m not as worried about having a lot happen at once.
An obvious thing I’m missing is a method for backing up the database and syncing it locally. This is really only a few more lines in the fabfile.
I also need to reimplement a previous method I had for copying the site’s Nginx configuration, though that may also be part of another half completed provisioning attempt.
This workflow has been painless to me as an individual maintaining a production copy of code that is version controlled and locally accessible. It allows me to test new plugins and themes before adding them to version control. It also allows me to quickly test specific revisions of WordPress core in production.
I’m not sure how well this would expand for a team of developers deploying code. There are likely some easy ways to tighten up loose ends, mostly around internal communication and defining a release workflow. I am also certain that Fabric is more powerful than how I am using it. I look forward to digging in deeper at some point.
content/… Don’t ever do this, ugh. Keeping it a directory up from WordPress is great, but keep it named
wp-content. It is possible some of my problems also came from changing my content domain to
content.jeremyfelt.com, but I blame a lot of it on
content/. My current favorite is