Making Your Capistrano Recipe Book

18,736 views

Published on

Talk given at January 2010 Sydney RORO (Ruby on Rails Oceania) meeting.

Published in: Technology, Business
0 Comments
13 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
18,736
On SlideShare
0
From Embeds
0
Number of Embeds
12,013
Actions
Shares
0
Downloads
120
Comments
0
Likes
13
Embeds 0
No embeds

No notes for slide

Making Your Capistrano Recipe Book

  1. 1. Making Your Capistrano Recipe Book Tim Riley @timriley
  2. 2. development: oauth_consumer_key: secret_oauth_thing oauth_consumer_secret: secret_oauth_thing namespace :gems do oauth_callback: "http://decafsucks.com/oauth_callback" task :install, :roles => :app do # App <<: *base sudo "sh -c 'cd #{release_path} && sudo RAILS_ENV=production rake gems:install'" set :application, "decafsucks" end test: &test end # Server oauth_consumer_key: secret_oauth_thing set :user, 'deployer' oauth_consumer_secret: secret_oauth_thing namespace :db do set :deploy_to, "/home/deployer/deployments/#{application}" oauth_callback: "http://decafsucks.com/oauth_callback" task :generate_yaml, :roles => :app do set :use_sudo, false <<: *base db_config = <<-EOF set :port, '2222' base: &base production: adapter: mysql role :app, '192.168.0.1' oauth_consumer_key: secret_oauth_thing encoding: utf8 role :web, '192.168.0.1' oauth_consumer_secret: secret_oauth_thing username: mysql_user role :db, '192.168.0.1', :primary => true oauth_callback: "http://decafsucks.com/oauth_callback" password: #{db_password} <<: *base socket: /var/run/mysqld/mysqld.sock # Other EOF set :db_password, Proc.new { Capistrano::CLI.password_prompt('DB password: ')} run "mkdir -p #{shared_path}/config" development: put twitter_config, "#{shared_path}/config/twitter_auth.yml" database: decafsucks_development # SCM end <<: *base set :scm, :git set :repository, 'git@somehwere.com/myapp.git' desc 'Make symlink for database yaml' test: &test set :branch, 'master' task :symlink, :roles => :app do database: decafsucks_test set :deploy_via, :remote_cache run "ln -nfs #{shared_path}/config/twitter_auth.yml #{release_path}/co <<: *base end default_run_options[:pty] = true end rumble: set :ssh_options, { :forward_agent => true } database: decafsucks_production namespace :sphinx do <<: *base # Passenger desc 'Create a directory to store the sphinx indexes' namespace :deploy do task :create_db_dir, :roles => :app do production: desc "Restarting mod_rails with restart.txt" run "mkdir -p #{shared_path}/sphinx" database: decafsucks_production task :restart, :roles => :app, :except => { :no_release => true } do end <<: *base run "touch #{current_path}/tmp/restart.txt" EOF end desc 'Generate a config yaml in shared path' run "mkdir -p #{shared_path}/config" task :generate_yaml, :roles => :app do put db_config, "#{shared_path}/config/database.yml" [:start, :stop].each do |t| sphinx_yaml = <<-EOF end desc "#{t} task is a no-op with mod_rails" development: &base task t, :roles => :app do ; end morphology: stem_en desc 'Make symlink for database yaml' end config_file: #{shared_path}/config/sphinx.conf task :symlink, :roles => :app do end test: run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml" <<: *base end before 'deploy:setup', 'db:generate_yaml' production: end before 'deploy:setup', 'twitter:generate_yaml' <<: *base before 'deploy:setup', 'sphinx:create_db_dir' EOF namespace :twitter do before 'deploy:setup', 'sphinx:generate_yaml' run "mkdir -p #{shared_path}/config" task :generate_yaml, :roles => :app do put sphinx_yaml, "#{shared_path}/config/sphinx.yml" twitter_config = <<-EOF after 'deploy:update_code', 'db:symlink' end base: &base after 'deploy:update_code', 'twitter:symlink' desc 'Symlink the sphinx yml and config files, and the db directory for strategy: oauth after 'deploy:update_code', 'sphinx:symlink' task :symlink, :roles => :app do base_url: "https://twitter.com" run "ln -nfs #{shared_path}/sphinx #{release_path}/db/sphi authorize_path: "/oauth/authenticate" # after 'deploy:update_code', 'gems:install' run "ln -nfs #{shared_path}/config/sphinx.yml #{release_path}/config/ api_timeout: 10 run "ln -nfs #{shared_path}/config/sphinx.conf #{release_path}/config/ remember_for: 14 # days end end
  3. 3. set :application, "decafsucks" set :user, 'deployer' set :deploy_to, "/home/deployer/deployments/#{application}" set :use_sudo, false role :app, '192.168.0.1' role :web, '192.168.0.1' role :db, '192.168.0.1', :primary => true set :scm, :git set :repository, 'git@git.mycorp.net:decafsucks.git’ set :branch, 'master' set :deploy_via, :remote_cache default_run_options[:pty] = true set :ssh_options, { :forward_agent => true }
  4. 4. namespace :deploy do desc "Restarting mod_rails with restart.txt" task :restart, :roles => :app, :except => { :no_release => true } do run "touch #{current_path}/tmp/restart.txt" end [:start, :stop].each do |t| desc "#{t} task is a no-op with mod_rails" task t, :roles => :app do ; end end end
  5. 5. before 'deploy:setup', 'sphinx:create_db_dir' before 'deploy:setup', 'sphinx:generate_yaml' after 'deploy:update_code', 'sphinx:symlink' namespace :sphinx do desc 'Create a directory to store the sphinx indexes' task :create_db_dir, :roles => :app do run "mkdir -p #{shared_path}/sphinx" end desc 'Generate a config yaml in shared path' task :generate_yaml, :roles => :app do sphinx_yaml = <<-EOF development: &base morphology: stem_en config_file: #{shared_path}/config/sphinx.conf test: <<: *base production: <<: *base EOF run "mkdir -p #{shared_path}/config" put sphinx_yaml, "#{shared_path}/config/sphinx.yml" end desc 'Symlink the sphinx yml and config files, and the db directory for storage of indexes' task :symlink, :roles => :app do run "ln -nfs #{shared_path}/sphinx #{release_path}/db/sphinx" run "ln -nfs #{shared_path}/config/sphinx.yml #{release_path}/config/sphinx.yml" run "ln -nfs #{shared_path}/config/sphinx.conf #{release_path}/config/sphinx.conf" end end
  6. 6. configuration = Capistrano::Configuration.respond_to?(:instance) ? Capistrano::Configuration.instance(:must_exist) : Capistrano.configuration(:must_exist) configuration.load do # stuff here... end
  7. 7. unless Capistrano::Configuration.respond_to?(:instance) abort "capistrano/ext/multistage requires Capistrano 2" end Capistrano::Configuration.instance.load do # stuff here... end
  8. 8. base.rb configuration.load do # User details _cset :user, 'deployer' _cset(:group) { user } # Application details _cset(:app_name) { abort "Specify the short name of your app, set :app_name, 'foo'" } set(:application) { "#{app_name}.mycorp.com" } _cset(:runner) { user } _cset :use_sudo, false # SCM settings _cset(:appdir) { "/home/#{user}/deployments/#{application}" } _cset :scm, 'git' set(:repository) { "git@git.mycorp.com:#{app_name}.git"} _cset :deploy_via, 'remote_cache' set(:deploy_to) { appdir } # Git settings for capistrano default_run_options[:pty] = true ssh_options[:forward_agent] = true end
  9. 9. common.rb def _cset(name, *args, &block) unless exists?(name) set(name, *args, &block) end end
  10. 10. base.rb configuration.load do # User details _cset :user, 'deployer' _cset(:group) { user } # Application details _cset(:app_name) { abort "Specify the short name of your app, set :app_name, 'foo'" } set(:application) { "#{app_name}.mycorp.com" } _cset(:runner) { user } _cset :use_sudo, false # SCM settings _cset(:appdir) { "/home/#{user}/deployments/#{application}" } _cset :scm, 'git' set(:repository) { "git@git.mycorp.com:#{app_name}.git"} _cset :deploy_via, 'remote_cache' set(:deploy_to) { appdir } # Git settings for capistrano default_run_options[:pty] = true ssh_options[:forward_agent] = true end
  11. 11. require 'capistrano/mycorp/common' configuration.load do _cset(:app_name) { abort "Specify the short name of your app, set :app_name, 'foo'" } before 'deploy:setup', 'sphinx:create_db_dir' before 'deploy:setup', 'sphinx:generate_yaml' after 'deploy:update_code', 'sphinx:symlink' namespace :sphinx do desc 'Create a directory to store the sphinx indexes' task :create_db_dir, :roles => :app do run "mkdir -p #{shared_path}/sphinx" thinking_ end desc 'Generate a config yaml in shared path' task :generate_yaml, :roles => :app do sphinx_yaml = <<-EOF development: &main_settings config_file: #{shared_path}/config/sphinx.conf sphinx.rb pid_file: #{shared_path}/pids/sphinx.pid production: <<: *main_settings EOF put sphinx_yaml, "#{shared_path}/config/sphinx.yml" end desc 'Symlink the sphinx yml and config files, and the db directory for storage of indexes' task :symlink, :roles => :app do run "ln -nfs #{shared_path}/sphinx #{release_path}/db/sphinx" run "ln -nfs #{shared_path}/config/sphinx.yml #{release_path}/config/sphinx.yml" run "ln -nfs #{shared_path}/config/sphinx.conf #{release_path}/config/sphinx.conf" end end end
  12. 12. Rakefile begin require 'jeweler' Jeweler::Tasks.new do |gemspec| gemspec.name = "capistrano-mycorp" gemspec.summary = "MyCorp recipes for Capistrano" gemspec.description = "MyCorp recipes for Capistrano" gemspec.email = "tim@openmonkey.com" gemspec.homepage = "http://github.com/timriley/capistrano-mycorp" gemspec.authors = ["Tim Riley"] end rescue LoadError puts "Jeweler not available. Install it with: gem install jeweler" end
  13. 13. echo "0.0.1" > VERSION rake gemspec rake build jeweler --help
  14. 14. set :application, "decafsucks" set :user, 'deployer' set :deploy_to, "/home/deployer/deployments/#{application}" namespace :sphinx do set :use_sudo, false desc 'Create a directory to store the sphinx indexes' task :create_db_dir, :roles => :app do role :app, '192.168.0.1' run "mkdir -p #{shared_path}/sphinx" role :web, '192.168.0.1' end role :db, '192.168.0.1', :primary => true desc 'Generate a config yaml in shared path' set :scm, :git task :generate_yaml, :roles => :app do set :repository, 'git@git.mycorp.net:decafsucks.git' sphinx_yaml = <<-EOF set :branch, 'master' development: &base set :deploy_via, :remote_cache morphology: stem_en config_file: #{shared_path}/config/sphinx.conf default_run_options[:pty] = true test: set :ssh_options, { :forward_agent => true } <<: *base production: namespace :deploy do <<: *base desc "Restarting mod_rails with restart.txt" EOF task :restart, :roles => :app, :except => { :no_release => true } do run "mkdir -p #{shared_path}/config" run "touch #{current_path}/tmp/restart.txt" put sphinx_yaml, "#{shared_path}/config/sphinx.yml" end end [:start, :stop].each do |t| desc 'Symlink the sphinx yml and config files, and the db directory for storage of indexes' desc "#{t} task is a no-op with mod_rails" task :symlink, :roles => :app do task t, :roles => :app do ; end run "ln -nfs #{shared_path}/sphinx #{release_path}/db/sphinx" end run "ln -nfs #{shared_path}/config/sphinx.yml #{release_path}/config/sphinx.yml" end run "ln -nfs #{shared_path}/config/sphinx.conf #{release_path}/config/sphinx.conf" end before 'deploy:setup', 'sphinx:create_db_dir' end before 'deploy:setup', 'sphinx:generate_yaml' after 'deploy:update_code', 'sphinx:symlink'
  15. 15. set :app_name, 'decafsucks' role :app, '192.168.0.1' role :web, '192.168.0.1' role :db, '192.168.0.1', :primary => true require 'capistrano/mycorp/base' require 'capistrano/mycorp/thinking_sphinx'
  16. 16. ★ Multistage defaults ★ Mounting shares ★ web:disable ★ Gem installation ★ Gem bundling ★ Populating config.yml ★ Populating database.yml ★ Thinking Sphinx ★ ...
  17. 17. Thank You! @timriley openmonkey.com timriley/capistrano-mycorp technicalpickles/jeweler

×