Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 1-10 of 14 total  RSS 

Deploying on a passenger / mod_rails host with capistrano

// add this to deploy.rb

namespace :mod_rails do
  desc <<-DESC
  Restart the application altering tmp/restart.txt for mod_rails.
  DESC
  task :restart, :roles => :app do
    run "touch  #{release_path}/tmp/restart.txt"
  end
end

namespace :deploy do
  %w(start restart).each { |name| task name, :roles => :app do mod_rails.restart end }
end

Rails Environment Specific Capistrano Includes/Overrides

This cap technique allows you to include environment specific tasks and namespaces as well as override anything in the master deploy.rb. Its rather simplistic.

Add your environment specific cap scripts into RAILS_ROOT/config/deployments/.

Example command-line usage:

# RAILS_ENV=production cap deploy

...or...

# cap deploy rails_env=beta


# Example needed variables at the top of your deploy.rb

set :default_env,  'beta'
set :rails_env,     ENV['rails_env'] || ENV['RAILS_ENV'] || default_env
set :extra_deploys, 'config/deployments/'

...

# Now add this to the bottom of your deploy.rb, last thing to load.

if extra_deploys && File.exists?(extra_deploys+rails_env+".rb")
  puts "Loaded #{extra_deploys+rails_env}.rb" if load extra_deploys+rails_env
else
  puts "Could not find #{extra_deploys+rails_env}.rb"
end



You may change your default_env or any other piece to fit into your deployments. The secret is "load" method call burried in that latter code portion above. The reason you load at the end of your deploy.rb is so you can override anything defined above that call in your environment specific scripts.

Upgrade rubygems and/or specific gems themselves via capistrano

When a latest RubyGems is released (e.g. 0.9.5 recently) or Rails (e.g. 2.0.2) you might want to push those upgrades to all your production machines.

Add these two tasks to your deploy.rb capistrano file (add namespaces for cap2.0 if you like)

  desc "Updates RubyGems version"
  task :gem_update_system do
    sudo "gem update --system"
  end

    
  desc "Install a RubyGem from remote source"
  task :gem_install do
    puts "USAGE: GEM=gemname cap gems_install" and next unless ENV['GEM']
    sudo "gem install #{ENV['GEM']} --no-ri --no-rdoc"
  end


To upgrade rubygems and rails, for example:

cap gem_update_system
GEM=rails cap gem_install

Mongrel and Apache fun with Capistrano 2.0

I got the Mongrel recipes from somewhere else -- I sadly don't remember where -- and modified them a bit.

namespace :deploy do
  namespace :mongrel do
    [ :stop, :start, :restart ].each do |t|
      desc "#{t.to_s.capitalize} the mongrel appserver"
      task t, :roles => :app do
        run "mongrel_rails cluster::#{t.to_s} --clean -C #{mongrel_conf}"
      end
    end
  end
  
  namespace :apache do
    desc "Start Apache"
    task :start, :roles => :web do
      sudo "/etc/init.d/httpd start > /dev/null"
    end

    desc "Stop Apache"
    task :stop, :roles => :web do
      sudo "/etc/init.d/httpd stop > /dev/null"
    end

    desc "Restart Apache"
    task :restart, :roles => :web do
      sudo "/etc/init.d/httpd restart > /dev/null"
    end
  end

  desc "Custom restart task for mongrel cluster"
  task :restart do
    deploy.mongrel.restart
    deploy.apache.restart
  end

  desc "Custom start task for mongrel cluster"
  task :start, :roles => :app do
    deploy.mongrel.start
    deploy.apache.start
  end

  desc "Custom stop task for mongrel cluster"
  task :stop, :roles => :app do
    deploy.apache.stop
    deploy.mongrel.stop
  end

end

Dump postgres production data into development database

When bug requests come in, its great to grab a copy of the current production (or system test env) data and sync it into your development database.

Here's a capistrano recipe for postgresql:

desc "Dumps target database into development db"
task :sync_db do
  env   = ENV['RAILS_ENV'] || ENV['DB'] || 'production'
  file  = "#{application}.sql.bz2"
  remote_file = "#{shared}/log/#{file}"
  run "pg_dump --clean --no-owner --no-privileges -U#{db_user} -h#{db_host} #{db_name}_#{env} | bzip2 > #{file}" do |ch, stream, out|
    ch.send_data "#{db_password}\n" if out =~ /^Password:/
    puts out
  end
  puts rsync = "rsync #{user}@#{domain}:#{file} tmp"
  `#{rsync}`
  puts depackage = "bzcat tmp/#{file} | psql #{local_db_dev}"
  `#{depackage}`
end

Capistrano logs

To get the last n lines from a remote log file, use this task

Usage: cap log [-s lines=100] [-s rails_env=production]
So, "cap log" returns 100 lines from production.

desc "Returns last lines of log file. Usage: cap log [-s lines=100] [-s rails_env=production]"
task :log do
  lines     = configuration.variables[:lines] || 100
  rails_env = configuration.variables[:rails_env] || 'production'
  run "tail -n #{lines} #{app_dir}/log/#{rails_env}.log" do |ch, stream, out|
    puts out
  end
end

Capistrano : apply local patches when deploying from an external source code repository

I've submitted patches to a couple rails apps, and want to run off of their SCM's trunk code, but with my local patches applied. These Capistrano tasks will take any files matching
patches/*.diff
in your local directory, and apply them before restarting your app.

task :after_setup do
  patches_setup
end

task :after_update_code do
  send_and_apply_patches
end

task :patches_setup do
  run "mkdir -p #{deploy_to}/#{shared_dir}/patches" 
end

task :send_and_apply_patches do
  Dir[File.join(File.dirname(__FILE__), '../patches/*.diff')].sort.each do |patch|
    puts "sending #{File.basename(patch)}"
    put(File.read(patch),
       "#{deploy_to}/#{shared_dir}/patches/#{File.basename(patch)}",
       :mode => 0777)
    puts "applying #{File.basename(patch)}"
    run "cd #{release_path}; patch -p0 < #{deploy_to}/#{shared_dir}/patches/#{File.basename(patch)}"
  end
end

Deploying to different locations with Capistrano

// description of your code here
In your deploy.rb file:

if ENV["SERVER"] && ENV["SERVER"] == "production"
  set :primary_server, "production.com"
  set :user, "ben"
elsif ENV["SERVER"] && ENV["SERVER"] == "staging"
  set :primary_server, "staging.local"
  set :user, "ben"
else
 ...
end

role :web, primary_server
role :app, primary_server
role :db,  primary_server, :primary => true



The you say:
rake deploy SERVER=staging

Capistrano Task Library for Deploying Subversion Tags

=begin

Capistrano Task Library > capistrano_svn_tags.rb
Created by Anil Bawa <anil@quotesque.net>
Enhanced by Sava Chankov <sava.chankov@gmail.com>
Distributed Under the BSD license

+ Task library to provide subversion tag support to Capistrano.

- place this file somewhere in your rails app (i suggest lib/tasks)
- add a 'require' statement in config/deploy.rb to load this file in
- run 'rake remote:deploy_tag [tagname]' to deploy a tag (you can provide your own custom implementation of the task - edit it below)
- tag rollbacks will work fine.
- this library overrides a capistrano core method, so if you wish to use the default release type (latest revision, deployed as timestamp) then comment out the require.

=end

Capistrano.configuration(:must_exist).load do

  set :svn_tag_dir, 'tags' # new config var to denote the tag sub-directory in the svn repository  
  
  desc <<-DESC
  Update all servers with the provided tag of the source code. All this does
  is do a checkout of the provided svn tag (as defined by the svn module).
  DESC
  task :update_tag, :roles => [:app, :db, :web] do
  
    puts "  * deploying tag #{release}"

    on_rollback { delete release_path, :recursive => true }
    source.checkout_tag(self)
    run <<-CMD
      rm -rf #{release_path}/log #{release_path}/public/system &&
      ln -nfs #{shared_path}/log #{release_path}/log &&
      ln -nfs #{shared_path}/system #{release_path}/public/system
    CMD

  end

  desc <<-DESC
  Deploy svn tag, reset symlink and restart server.
  DESC
  task :deploy_tag, :roles => [:app, :db, :web] do
    set_release_tag

    transaction do
      update_tag    
      symlink
      compile_mo
    end
  end
  
  desc <<-DESC
  Deploy svn tag, migrate, compile .po files to .mo and reset symlink and restart server.
  Note that everything is done in a transaction
  DESC
  task :deploy_tag_with_migrations, :roles => [:app, :db, :web] do
    set_release_tag

    transaction do
      update_tag
      symlink
      migrate
      compile_mo    
    end
  end
  
  def set_release_tag
    set :release, ENV['TAG']
    unless release
      puts "  * no tag specified, assuming latest"
      set(:release) {source.latest_tag}
    end
  end
end

module Capistrano

  #override a configuration object method to return the correct release_path for the tag.
  class Configuration
  
    # Return the full path to the named release. If a release is not specified,
    # the provided tag name (passed as a cli parameter) is used.
    def tag_path(tag_name = release)
      File.join(releases_path, tag_name)
    end
    alias_method :release_path, :tag_path
    
  end
  
  # add a method to the subversion object to checkout tags
  module SCM
    class Subversion
      
      def latest_tag
        configuration.logger.debug "querying latest tag ..." unless @latest_revision
        tags_dir = configuration.repository + '/' + configuration.svn_tag_dir + '/'
        @latest_revision = svn_ls(tags_dir).split("\n").last.chomp('/')
      end
      alias_method :latest_revision, :latest_tag
      
      # checkout a tag from a pre-configured svn tag dir.
      def checkout_tag(actor)
        op = configuration[:checkout] || "co"
        username = configuration[:svn_username] ? "--username #{configuration[:svn_username]}" : ""
        command = "#{svn} #{op} #{username} -q #{configuration.repository}/#{configuration.svn_tag_dir}/#{configuration.release} #{actor.release_path} &&"        
        run_checkout(actor, command, &svn_stream_handler(actor))         
      end
      
    private
      def svn_ls(path)
        `svn ls #{path}`
      end
    end
  end
end

SVN revision from shell

I use this to set the subject of an email that notifies my team of a Capistrano deploy. The part of interest is how it gets the subversion revision number with a few piped shell commands.

echo "Subject: [rake deploy] Deployed revision `cd /home/www/current ; svn info | grep Revision | sed "s/Revision: //"` on `hostname` at `date`" > ~/sendmail_tmp
« Newer Snippets
Older Snippets »
Showing 1-10 of 14 total  RSS