A couple weeks ago, I started on a bit of
tirade discussion about version control that turned into a short series – Version Control and You Part 1, Part 2, and Part 3 – and while that series may expand later, I'm moving onto the next step of the process….
For some people, the idea of deploying code keeps them up at night. Every time they consider what it takes to deploy their latest and greatest changes, they break into a cold sweat. They think they know the changes they've made. They think they know the code/db changes required. Generally this type of team has a deployment process of "well, we ftp it to the server and click around to see if it works".
For the record, that's not a deployment strategy. It's the fastest way to break everything and
piss off frustrate your users.
For some people, the idea of deploying is a minor issue. They have systems and policies in place to make the overall process relatively painless, repeatable, and generally not a "lose sleep" kind of issue. For the past few years, I've been developing and refining my various deployment practices making sure they work properly and effectively for my environments… here's what I've learned:
First, I started this exercise in Java using Ant. Honestly, it didn't much easier and this is one of the areas where Java – and their entire community – has led the way and really set a high bar for ease of use. Ant had cvs (and now svn!) tasks that could do all the heavy lifting for you. By tweaking out your build.xml script, you could have the script get the latest snapshot of the code, compile your classes, run Unit Tests, compile your supporting jsp's, upload the relevant jars/jsp's to the proper server and restart your container. At any step, if something failed, it stopped and shared the results. Hard to beat. Unfortunately, this doesn't handle the database changes…
Next, in mid-2005, I steadily moved out of the Java world and entirely into PHP. At the time, the tools were non-existant at minimum, embryonic at best. Luckily, a number of projects – like Phing* – have stepped into the breach to duplicate and mimic the functionality of Ant. In the meantime, you can still do many of those things manually and reduce your risk of breaking everything. How hard is it to type: svn up ? Odds are that will solve your "oops, I missed a file" problem immediately.
Even more fun is a simple trick I figured out last year. When most people deploy code, the deploy direcly over their existing code, so if something's broken, rolling back may be painful. How about this for an idea? Don't. In many of my web environments, I created a simple /code folder and deployed tagged releases within it using a specific date. Then I create a symlink from htdocs to /code/latest folder…. and that's it. For example, if I deployed every Sunday, my structure might look like this:
/code/20071203/ (previous release of my useful code)
/code/20071210/ (latest release of my useful code)
/htdocs -> /code/20071203
To "deploy" the latest version, I simply point the symlink to the new directory. To roll it back, I point it at the old one. The total deployment time is the time to remove/create the symlink. There's no momentary oddities where some of the files have been updated, but not all. Unfortunately, this doesn't handle the database changes…
* Disclaimer: The Project Lead of Phing – Hans Lellelid – is a local DCPHP Dev Group member and active on the mailing lists. If you're a PHP'er in DC or interested in PHP in DC, check out the list.
Finally, in the last few months, I've been working on a major Rails project. Despite some of the valid complaints you've heard about Rails from Terry Chay, one of the single best things that they did right… Migrations. If you combine this with something as simple as svn up, deploying can happen in a single command. If you bring something like Capistrano into the picture, it gets even easier… and after all, since we're lazy, the less code/clicking involved, the better for everyone.
Overall, in the last few years, the tools have come a long way. And more importantly, the tools and concepts have moved across languages. To the best of my knowledge, Java was the one that got the ball rolling – yes, ignoring make for now – and set an incredibly high bar. Luckily, the other communities responded in kind learning from the lessons and mistakes to move things farther and faster. Isn't that the point of Open Source?
Despite all of this, you may have noticed, I've glazed over a significant point:
Who does the deployment?
Any guess what Part 2 will be?