Automatic Deployment for Rails

gga

For the Rails applications we’re building at work, as well as all the
standard continuous integration features, we also automatically deploy
our applications. That is, every time we submit code a central server
is automatically updated with a new release. Before running tests.

We’re pretty happy with this set up. It’s already found a couple of
bugs in some plugins we’re using. More on that in an upcoming
post. Here’s how we made our automatic deployment work. We’re using
Capistrano for our deployment scripts, we’re deploying to Phusion
Passenger running under Apache on FreeBSD and our continuous
integration server runs an Ant script.

These instructions describe how to set up a Apache 2.2 web server with
Phusion Passenger on FreeBSD; the Ant script to automatically deploy
and how to configure a Rails app to be deployed like this.

This will give you two new environments for your apps: DEVTEST and
UAT. UAT is a user acceptance testing environment, our system testers
and analysts use and own this environment. We don’t automatically
deploy to here, we release to here. DEVTEST is the environment we
automatically deploy to.

Setting up Your Server

Installing Phusion Passenger

Installing Phusion Passenger on a FreeBSD server is no different to
installing anywhere else:

$ sudo gem install passenger
$ sudo passenger-install-apache2-module

Configuring Apache

At the end of the second step, the installer tells you to add some
config to the end of your Apache config. On FreeBSD, edit this with:

Unless you want to use two different servers for the two environments,
you’ll need to use named virtual hosts, and ask your friendly
administrator to add CNAME records to your DNS server pointing devtest
and uat at the same physical server. They’ll know what you mean.

Create a Local User

You’ll need a local user on your server. This is the user that will
run the automatic deployments.

These last two directories, and everything under them should be owned
by the deployment user you created above.

$ sudo chown -R deploy-robot:www devtest uat

Gems

Finally, there are some gems you’ll need installed on the target
deployment server. Some of these depend on FreeBSD ports.

$ cd /usr/ports/comms/ruby-termios
$ sudo make install clean

And then just a couple of gems.

$ sudo gem install termios
$ sudo gem install capistrano

And that’s it for initial server configuration. There will be some
more configuration when first deploying an application.

Preparing Your Application

Capistrano Config

Capify your application:

$ cd app
$ capify .

Edit your capistrano rules in deploy.rb. You’ll want them to look
something like the following. These rules use no source control
system to get the code. Our continuous integration server takes care
of checking out the code, so it’s easier to deploy from the local code
copy. And, this way we can be sure each deployment only contains one
changelist.

Ant Deployment Scripts

Our company has an in-house continuous integration server. We’d be too
embarrassed at cocktail parties if we didn’t have our own. Yes, yes, I
know this is completely ridiculous. And to make it even worse, it only
runs Ant scripts. Sigh. Anyway, here’s how you make Ant automatically
deploy an application to devtest.

Ant macros, while quite insane, are generally a better way to define
new tasks than the complete insanity of trying to write a whole Ant
plugin in Java. These macros define low-level tasks to run rake and
capistrano tasks, and then use these to build up higher level tasks
like test and deploy. All these tasks assume that Ant has been run
from the directory immediately above your Rails app directory.

In a file called project.properties, set your server, user name and
password. Having the password here is unfortunate, but it is a local
account, with limited privileges on an internal server. Your call.

The large comment block is just helpful for other developers trying to
add another application. From here, to try this out:

$ ant

It should run the deployment, and then run the test suites. If that works as you expect, then just configure your continuous integration server to run Ant over that file on every submit.

Hopefully this is of use to someone. Though this is how our
environment is configured, I have written this all from memory, so I
might have missed a critical step somewhere. Please let me know if
there’s anything that needs to be changed.