capistrano

André Roaldseth - @androa

WHAT'S CAPISTRANO?






Originally a tool for deploying code.







Evolved into remote multi-server automation tool.







Uses SSH.







Does everything in parallel.

Requirements






Ruby >= 1.8.7






SSH access to all servers,
preferably with public keys.

Terminology




  • Task
  • Recipe
  • Namespace
  • Role
  • Staging

Task






A concrete set of commands to execute.

Recipe






A collection of tasks.

Namespace






Organizes tasks within recipes and
avoids naming collisions.

Role




Servers can have different roles like 
web
cache
database
static

Staging



Refers to each environment being a stage.

Usually means different servers.
Can also include configuration.
Or even different tasks.

No stage can be named "stage"!

How it works





Connects to all servers through SSH.
Cycles through tasks from recipe.
Perform tasks in parallel.

cap shell



$ cap production shell
    triggering load callbacks
  * executing `production'
    triggering start callbacks for `shell'
  * executing `multistage:ensure'
  * executing `shell'
============================================================
Welcome to the interactive Capistrano shell! This is an 
experimental feature, and is liable to change in future 
releases. Type 'help' for a summary of how to use the shell.
------------------------------------------------------------
cap> echo "Hello"
 ** [out :: server-web-02.int.vgnett.no] Hello
 ** [out :: server-web-01.int.vgnett.no] Hello
 



deployment

Disclaimer - ruby on rails!




Capistrano is by default designed 
for deploying Ruby on Rails applications.

This requires that we remove
some default behaviour.

Version control systems



Git
CVS
darcs
Accurev
Perforce
Mercurial
Subversion

Strategies



Dictates how the Version Control System is used.

Copy
Checkout
Export
Remote cache

COPY STRATEGY






Local checkout, 
copies files to remote host by SSH.

Checkout strategy






Checkout on each remote host,
fresh files with VCS metadata.

Export strategy






Export on each remote host, 
fresh files without VCS metadata.

remote_Cached strategy






Checkout on each remote host,
which is updated and copied to deploy path.

Getting started






$ cd my_project
$ capify .


capistrano




Capistrano is executed with "cap".

cap iterates up the tree to find a Capfile.

capfile



Capfile is the first file cap looks for, 
 as it contains instructions for cap to work.

Usually loads deploy.rb

load 'deploy' # Default deploy recipe
load 'config/deploy' # Local customized recipe

config/deploy.rb





Created in "config/", can be moved anywhere.

Contains configuration and recipe.

Sample config/deploy.rb


set :application "vgtv"

set :scm, :subversion
set :repository, "svn+ssh://svn.int.vgnett.no/svn/somerepo"
set :deploy_via, :remote_cache
ssh_options[:forward_agent] = true set :deploy_to, "/services/application/#{application}" role :web "server-web-01.int.vgnett.no" role :web "server-web-02.int.vgnett.no" set :use_sudo, false after "deploy:restart", "deploy:cleanup" set :shared_children, %w{} set :public_children, %w{css js img}

deploy!

First time for a new server:

$ cap deploy:setup


Creates this folder structure:

$ tree
.
|-- current -> releases/20120927122114/
|-- releases
|   |-- 20120924121738
|   |-- 20120926075745
|   `-- 20120927122114
`-- shared
    `-- logs


Every following deploy:

$ cap deploy

multiple stages/environments

config/deploy.rb:

require "capistrano/ext/multistage"
set :stages, %w{production staging}
set :default_stage, "staging"
set :stage_dir "configs/stages"


config/stages/production.rb

role :web, "production-web-01.int.vgnett.no"
role :web, "production-web-02.int.vgnett.no"


config/stages/staging.rb

role :web, "staging-web-01.int.vgnett.no"

deploying with multistage



Deploying to staging:
$ cap deploy
$ cap staging deploy

Deploying to production:
$ cap production deploy

Part deploys


Get a list of all tasks:
$ cap -T
cap deploy                # Deploys your project.
cap deploy:check          # Test deployment dependencies.
cap deploy:cleanup        # Clean up old releases.
...
cap invoke                # Invoke a single command on the remotes
cap shell                 # Begin an interactive Capistrano session


Run a single task:

$ cap production deploy:cleanup

Cool stuff

create .htaccess with environment



before "deploy:create_symlink", "deploy:set_environment"

namespace :deploy do
    task :set_environment do
        run "cp #{current_release}/public/.htaccess-dist " +
            "#{current_release}/public/.htaccess"
 
        run "sed -i -r 's/APPLICATION_ENV \\w+/APPLICATION_ENV " +
            "#{stage}/' #{current_release}/public/.htaccess"
    end
end

Preprocess LESS files



before "deploy:create_symlink", "deploy:preprocess_less"
namespace :deploy do
    task :preprocess_less do
        run "lessc -x #{current_release}/public/css/main.less " +
            "#{current_release}/public/css/compressed.css"
 
        run "sed -i -r 's/main\.less/main.css/' " +
            "#{current_release}/application/layouts/layout.phtml" run "rm #{current_release/public/css/*.less"
    end
end


Build require.js


before "deploy:create_symlink", "deploy:preprocess_rjs"

namespace :deploy do
    task :preprocess_rjs do
        run "mv #{current_release}/public/js " +
            "#{current_release}/public/js-src"

        run "mkdir #{current_release}/public/js"

        run "r.js -o #{current_release}/tools/js/build.js " +
            "baseUrl=#{current_release}/public/js-src/ " +
            "out=#{current_release}/public/js/bootstrap.js"

        run "rm -rf #{current_release}/public/js-src/"
    end
end

Move images to static server



before "deploy:create_symlink", "deploy:move_static_files"

set :static_server, "static.int.vgnett.no"
set :static_path, "/services/static/files"

namespace :deploy do
    task :move_static_files do
        run "rsync -O --exclude=.svn -a " + 
            "#{current_release}/public/images/" +
            "#{static_server}:#{static_path"

        run "rm -rf #{current_release}/public/images/"
    end
end

Yey, finished! 


\o/

Questions?

deployment with capistrano

By André Roaldseth

deployment with capistrano

  • 1,713