Remote builds with Capistrano

Capistrano is a very nice open source tool for executing commands on one or multiple remote servers via SSH. Capistrano is written in Ruby and uses a rake-like DSL for its tasks. Its main use is to deploy web applications, Rails in particular, but it may be used for much more. Want to try? It’s very easy to getting started.

In a recent project I used Capistrano for building and installing a shared library, written in C. The library had to be built for several platforms on servers with limited Internet access. Before I started using Capistrano I spent several minutes each time just to upload the latest source code, build, and then download the shared library. Of course, it still takes time using Capistrano, but now everything is automated. Even the password input can be automated by using pre-entered passwords (not recommended) or SSH keys. The capfile with the complete task description is actually just a few lines of code.

task :build, :hosts => "johan@build-host.example.com" do
  puts %x[svn export trunk] # executing local command - just plain Ruby
  run "rm -rf my_app" # cleaning up old directory on server
  upload("my_app", ".", :via => :scp, :recursive => true) # upload source code
  run "cd my_app;scons" # build on server
  download("my-app/dist/my_app.so", "remote_build", :via => :scp, :recursive => false) # download built shared library
end

Thanks to the simple DSL it should be quite easy to follow the code, even without any Ruby experience. Note that cd my_app;scons cannot be divided as all commands are executed as sh -c '<command>' in the user’s home directory by default.

The command to execute the task from terminal is:

cap -p build

The -p argument will tell Capistrano to ask for password immediately, rather than waiting for the first remote command. This is quite useful if there are any time-consuming local commands to be executed before the first remote command.

After each build I wanted to install the shared library on all test servers. With Capistrano that was of course very easy – I just added a new target to the capfile.

task :install, :hosts => ["test-host1.example.com", "test-host2.example.com"] do
  set :user, "johan" # alternative way of setting user
  run "rm -rf remote_build" # cleaning up old directory
  upload("remote_build", ".", :via => :scp, :recursive => true) # upload built shared library
  sudo "cp remote_build/* /usr/lib/my_app/", :pty => true # install as root and with psuedo-tty
end

Note that the last command will be executed with psuedo-tty if possible. Normally you will have to have a tty when executing a command with sudo.

Capistrano was really the perfect tool for me in my project. It really saved me a lot of time and needless effort. I hope you too will find it useful.

You can also read my follow-up post on Capistrano – Capistrano and Net:SSH with login shell.

This Post Has One Comment

Leave a Reply

Close Menu