My Deployment Process

Inspired by Anthony Killeen's post yesterday on how he starts a project, I thought I'd quickly share how I approach deployment of a site/project.

My preferred method is via a couple of Bash scripts using SSH rather than FTP. There are a couple of reasons for this. I can define the logic of deploying a particular project in the script so that any other developers working on the project know what is needed to be done in order to deploy the code (things like which directories need to be writable, etc.).  I also aim to minimise any disruption to a live site by ensuring the deployment doesn't affect the existing site until the last minute.

I use either SVN (as in my examples below) or Git to version control my code and deploy from my latest commit to the trunk branch (working from a separate dev branch). My first deployment script handles this and any other logic needed before switching to the new code:-

rm -rf www_new
svn export [URL to SVN repository]/my_project/trunk/www www_new \ --username [username] --password [password]

# Make directories writable and clear the cache
chmod -R www_new/app/tmp
rm -rf www_new/app/tmp/cache/*/*

# Create symbolic link to the file uploads directory
rm -rf www_new/app/webroot/files/uploads 2> /dev/null
ln -s /home/my_project/statics/uploads \ /home/my_project/www_new/app/webroot/files/uploads

I'm calling the script from the directory above the webroot (e.g. /home/my_project). The script does several things.

Firstly it exports the new code from SVN (or Git) to a new directory www_new; next it ensure that any directories that need to be writable are and that caches are cleared (although the cache files shouldn't really be being committed in the first place). Finally it creates symbolic links to directories containing content that is uploaded via the site/project.

The symbolic link part is to prevent site content being overwritten during deployment. I host files that a user might upload to a site outside the webroot in a statics directory. These can be files such as images uploaded as part of a CMS. The symbolic link ensures that the files will still be seen as if they were in the webroot as expected.

At this point the code should be ready for pushing live. If there are any database changes that need to be done now is the time to do them (preferably via an SQL script to make the alterations).

Then I run my second script to finally put the newly deployed code live:-

rm -rf www_old
mv www www_old
mv www_new www

This just swaps the existing code into a backup directory and the new code to the webroot. This is a quick process that will be virtually unnoticeable by anyone visiting the site.

I do this last part as a separate script just in case something went wrong with the first script (reported as errors in the terminal). You'll notice that when I remove the uploads directory to prepare the symbolic link I have 2> /dev/null at the end of the command; that's because I expect this line to error as the directory should really be being ignored by SVN, but just in case someone's committed it I ignore the errors and carry on making the link.

If after pushing the newly deployed code live something is wrong the deployment can quickly be reversed calling a script:-

mv www www_new
mv www_old www

So that's how I handle deployments (whenever I have access to SSH). Having worked like this for the last year I hate having to revert to uploading individual files to FTP as I inevitably find something goes wrong, or parts of the site break during the process. The ability to quickly reverse the deployment if something goes wrong is really great too.

How do you handle deployment?

Related Content

Published on