I view my job as shepherding code from its inception in a Vim buffer, in a terminal session, in my development environment, until it makes it up into production in our space-age cloud app architecture. Anything less than that will result in mistakes, missed deadlines, and unfulfilled promises. It will also create unnecessary friction.
How can we get there? I wanted to share my thoughts on things you can do to reduce the deployment friction, even if you can’t get to continuous delivery any time soon.
Identical Environments
Failure to have a development environment that matches your production environment as closely as possible is the number one cause of the oft-used “unable to duplicate” response to a bug. The rise of easy-to-use virtual machine tools like VMware and VirtualBox means that it is easier than ever to duplicate your production environment on your desktop or laptop.
It also allows you to experiment with new features and work on code that can potentially alter or destroy data. Accidentally erased an entire table? No problem, just grab another copy of the virtual machine you were using and try again.
Environmentally-Aware Apps
If you are using third-party APIs in your app, you can often use a sandbox for testing purposes, and the real deal in production. You might also want to use separate databases for your staging and production servers. Either way, your app needs to know where it is actually running so you can control what it communicates with.
Web server environment variables are good for this when coupled with a registry that contains information unique to each environment where your application runs.
Automated Tests
Yes, I know, I know. Testing is a holy war unto itself — even more vicious than tabs versus spaces. Sometimes, your app is incredibly difficult to test in an automated fashion. I understand, but you do have options.
Your best option is to start using PHPUnit for your testing needs, as it can be run from the command line, which also means that running your tests could be triggered by a commit to your version control repository.
If you can’t do that, consider a tool like Selenium, which can run automated tasks in a browser for you and report back its findings. With a little work, you can get Selenium to also ensure certain values are present on specific pages.
Push-Button Deployment
Manual deployments are full of potential problems if they are beyond issuing one command. Database changes, asset compression, minifcation of JavaScript, restarting of services — the list of tasks that need to be performed as part of a “normal deployment” grows longer with every passing day. Every step is an opportunity to make a mistake that could have huge implications.
Tools like Phing, Capistrano, or even Bash can quickly and easily reduce your deployment process to the execution of one command.
Keep Fighting the Fight
Creating frictionless deployment workflows are hard, but they are worth the effort, because once you’ve reached that point, you’re able to concentrate on solving difficult problems instead of worrying about whether or not your new code is going to work this time.
Developer Gift
I can’t think of any programmer who wouldn’t benefit from having a copy of The Pragmatic Programmer, by Andrew Hunt and David Thomas. Mine is well-worn from its use as a reminder that while we are sometimes solving difficult problems, there are often simple solutions to them.