Child pages
  • Automating Application Deployment with Capistrano (Overview)

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Capistrano is a deployment system written on Ruby. Actually you don't have to know ruby if you want to use Capistrano - you'll still be able to implement your basic tasks. But if you want to gain real power and control on your deployment scenarios, some knowledge or ruby will greatly help.

How to install Capistrano

Here is the official Capistrano installation instructon page: http://www.capify.org/install. On Leopard all you need to do is to run the following command with root privileges:

...

On 10.4 you'll have to install ruby and rubygems prior to running this command. The simplest way to do this is to use binary installers.

Must-read article about Capistrano

Basics of using Capistrano are well described on its official site: http://www.capify.org/getting-started/basics

Writing simple deployment recipe

Before we write simple deployment recipe, I'd like to highlight 3 things about Capistrano (they are always highlighted in most number of articles about Capistrano, but still...):

...

Let's implement the :deploy task to do this:

1. Pack the BugTracker.woa into tar.gz archive.

This step should be done locally - we don't need to use Capistrano's main feature of executing ssh-commands in parallel on multiple servers.
So the code will be:

...

  • The postfix style of conditional operators - it's a kind of syntactic sugar that makes code more readable.
  • The $? variable which contains the status of the last executed shell command. You can find out more about this variable from Ruby documentation by executing the following command: "ri Process::Status" ($? contains the object of class Process::Status).

2. Copy the archive to the remote server.

Here's how it can be done:

...

This will copy BugTracker.woa.tar.gz to all servers specified for :app role (because our :deploy task is associated with this role). Capistrano will ask you for username and password to do the copying. It's quite inconvenient to enter username and password each time - so you probably should setup SSH public key authentication.

3. Remove previous deployment on the remote server.

This will look like this:

...

This will remove the /Library/WebObjects/Applications/BugTracker.woa folder on all servers specified for :app role. Notice that we've used "run" instead of "system". There is a great difference between these commands. "system" executes commands locally whereas "run" executes them on all remote servers specified for the current role. Another thing to notice the -f flag used for rm command. Capistrano will throw an exception and exit immediately if one of the commands executed on remote servers fail. Without -f flag rm will fail when there's no "/Library/WebObjects/Applications/BugTracker.woa" folder. This can happen during the first deployment, for example.

4. Unpack the archive.

Nothing new in this code:

...

You can change "localhost" to any hostname you want, or even specify several hostnames separated with commas. This script is the simplest one, but it already does plenty of stuff - and can be used in some simple scenarios. Let's complicate things a bit.

Cleanup

Let's write a cleanup task in order not to leave tar.gz archives both on our local machine and on remote servers. The task can look like this:

...

Yes, that's all. Now if :deploy tasks finishes successfully :cleanup task will be executed automatically.

Using variables

You can use variable in capistrano scripts. You can set then with the "set" command:

...

Note that in upload and FileUtils.rm_f calls variable names are used without any additional symbols - that's because they're not the part of any string literal - so they're used as simple ruby variables (well actually things are much more complicated - but at least they look like simple ruby variables).

Moving global definitions to /etc/capistrano.conf

Capistrano processes /etc/capistrano.conf file before processing any recipe. If you use several recipes for multiple projects that are hosted on the same deployment server, you will still have to specify :app role in every recipe. To avoid such duplication you can move the role definition to /etc/capistrano.conf. Also some general variable definitions can be moved there. In our case it's the :wo_apps_path variable.

Conclusion

Actually, with this brief overview of Capistrano features, you'll be able to write quite complicated deployment recipes. But it won't come as a surprise if I say that Capistrano can do a lot more. You can embed capistrano scripts into the ruby code, define multiple deployment configurations in single capistrano file, process output from servers and more and more... I'll write about these topics as soon as possible.