One of my first tasks at INN was to familiarize myself with the tools and technology the team currently uses.
What I noticed was that our deployment process was pretty darned manual. We host a number of our WordPress sites on WP Engine and while they allow deployment via git and access via SFTP, they don’t give us shell access to the server. So our deployment process up until this point has involved an FTP client, dragging and dropping files for transfer, maybe picking and choosing parts of our code to deploy based on what we've been hacking on. This approach works, but is fragile and requires a lot more thinking than I'm typically willing to do. Remember, laziness is a virtue.
Having a scripted deployment process means that the steps to deploy your code will be the same no matter who has the responsibility. Keeping a repo with your deployment scripts means the process is documented and can be critiqued and iterated upon.
We’re using Fabric because I am familiar with it. By all means, use Capistrano or some other deployment tool. Write a few shell scripts if that’s what you’re comfortable with. Do what you can to put the software to work for you.
A sound deployment strategy meets these criteria:
Want to deploy via git or sftp? Deploy a specific branch? Want to minify and compress assets before deployment? Maybe tag a commit for rollback purposes? Your deployment strategy should be extensible enough to accommodate these things and require little to no input from you. Write a script once and put it to work.
$ fab staging branch:exciting_new_feature deploy
Type the deployment command into your shell and hit enter.
$ fab staging master deploy
If something goes wrong, issue another command to revert to a previous state and deploy.
$ fab staging rollback deploy
Fabric, git-ftp and WPEngine
Fabric is a wonderful Python library that allows you to script away application deployments and remote system administration tasks. It provides a way to wrap up what would otherwise be complex git commands/workflows in simple, easy to remember, fab commands.
Some of the things our fabfile is set up to handle include:
- Use git-ftp to deploy files to WP Engine via sftp.
- Check the commit hash of currently-deployed code and automatically tag it is as a rollback point.
- Allow us to checkout and deploy a specific branch to a specific environment (i.e. master or stable to staging or production).
Why use git-ftp? In our experience, git deployment for WP Engine has been difficult to use and unreliable. Also, WP Engine requires an entire WordPress install as the basis for your repository, which isn’t how most of our repos are structured. Git-ftp allows us to work around these issues.
However, if we want to move to a git push-based deployment strategy or expand our toolkit to work with environments outside of WP Engine, adjusting or adding to our fabfile is trivial.
If you want to use our deployment tools with your project, you can follow the instructions in the README included in the repo. The README holds all the details regarding software prerequisites and how to install them.
If you’re already familiar with Python, Fabric and have your dev environment set up, you can find the “quick start” steps below.
$ git submodule add https://github.com/INN/deploy-tools.git tools
Then copy the files from tools/examples to the root of your project:
$ cp -Rf tools/examples/* ./
Finally, edit `fabfile.py` to use your WPEngine host, username and password:
# Environments def production(): """ Work on production environment """ env.settings = 'production' env.hosts = [‘mywpinstall.wpengine.com’, ] env.user = ‘mywpinstallusername’ env.password = ‘mywpinstallpassword’
After that, add and commit your changes. At this point, you should be able to deploy:
$ fab staging master deploy
If you want to perform a dry run beforehand to see exactly what files will be transferred:
$ fab staging master dry_run deploy
If you want to see a list of all available commands:
$ fab -l Available commands: branch Work on any specified branch. deploy Deploy local copy of repository to target environment. dry_run Don't transfer files, just output what would happen during a real deployment. master Work on development branch. path Specify the project's path on remote server. production Work on production environment rollback Deploy the most recent rollback point. stable Work on stable branch. staging Work on staging environment verify_prerequisites Checks to make sure you have curl (with ssh) and git-ftp installed, installs them if you do not.
Future plans include adding commands to handle asset minification and compression.
If you'd like to contribute, you can fork the code here.