Created
October 4, 2012 16:15
-
-
Save acidlabs-snippets/3834683 to your computer and use it in GitHub Desktop.
Rails 3.1+ Multistage deployment with Capistrano #rails #deployment #capistrano
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### This gist outlines a generic implementation of multistage deployment with Capistrano for Rails 3.1+. | |
# | |
# Usage: | |
# | |
# cap #{stage} deploy:setup | |
# cap #{stage} deploy:cold | |
# cap #{stage} deploy | |
# | |
# etc. | |
# Gemfile | |
# --- | |
gem 'capistrano' | |
gem 'foreman' | |
# --- | |
# Capfile | |
# --- | |
load 'deploy' | |
# If you don't want assets pipiline support, comment the line below | |
load 'deploy/assets' | |
Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } | |
load 'config/deploy' | |
# --- | |
# config/environments/orange.rb, | |
# config/environments/lemon.rb | |
# --- | |
# copy+paste production.rb | |
# --- | |
# config/procfile/orange | |
# --- | |
# If you like thin, this'd go like below. | |
web: nohup bundle exec thin -C ../thin/orange.yml start | |
# --- | |
# config/procfile/lemon | |
# --- | |
# Ah! I knew it, you like unicorns! Well then, as below for ya' unicorny fella'. | |
web: nohup bundle exec unicorn -c ../unicorn/lemon.rb -D | |
# --- | |
# config/deploy/orange.rb | |
# --- | |
# Server Settings. The port is optional, default to 22. | |
server "awesome.acid.cl:22", :web, :app, :db, primary: true | |
# User in the remote server. This is the user who's going to be used to deploy, and must have proper permissions. | |
set :user, "awesome" | |
# Appstage is the name you want the application to have in the server. | |
# It's used to set the folder name, the upstart config and other nifty stuff. | |
set :appstage, "awesome.orange" | |
# Folder in the remote server where the revisions are going to be deployed. | |
set :deploy_to, "/home/#{user}/#{appstage}" | |
# The branch that's going to be checked out. Releases are going to be made everytime there's a new revision (+x commits ahead). | |
set :branch, "orange" | |
# --- | |
# config/deploy/lemon.rb | |
# --- | |
# Server Settings. The port is optional, default to 22. | |
server "awesome.acid.cl:22", :web, :app, :db, primary: true | |
# User in the remote server. This is the user who's going to be used to deploy, and must have proper permissions. | |
set :user, "awesome" | |
# Appstage is the name you want the application to have in the server. | |
# It's used to set the folder name, the upstart config and other nifty stuff. | |
set :appstage, "awesome.lemon" | |
# Folder in the remote server where the revisions are going to be deployed. | |
set :deploy_to, "/home/#{user}/#{appstage}" | |
# The branch that's going to be checked out. Releases are going to be made everytime there's a new revision (+x commits ahead). | |
set :branch, "lemon" | |
# --- | |
# ./config/deploy.rb | |
# --- | |
require "bundler/capistrano" | |
# Enable multistage. | |
require "capistrano/ext/multistage" | |
# Declare the stages. The stages should follow the names you gave them in config/environments/* . | |
set :stages, %w(orange lemon) | |
# Set the default stage | |
set :default_stage, "lemon" | |
# The application name is used to determine what repository to pull from, name databases and other nifty stuff. | |
set :application, "awesome" | |
# Use sudo when deploying the application. Dunno what's default but true is evil. | |
set :use_sudo, false | |
# Choose the Source Control Management tool of your preference. | |
# (Don't. Really. Use git). | |
set :scm, :git | |
# Set the repository we're going to pull from. | |
# (Sorry, no multirepo, just multistage). | |
set :repository, "[email protected]:#{application}.git" | |
# Setup the way you want the deploy to be done. I sincerely suggest using :remote_cache. | |
set :deploy_via, :remote_cache | |
# Pseudo Terminals. If you want password prompt to work this must be true. | |
default_run_options[:pty] = true | |
# Imagine you ask a friend to give you his car keys to drive it by yourself. | |
ssh_options[:forward_agent] = true | |
set :database_username, user | |
set :database_password, "weloveacid" | |
namespace :deploy do | |
desc "Export the foreman config file to upstart" | |
task :generate_upstart, roles: :app, except: { no_release: true } do | |
run [ | |
"cd #{current_release}", | |
"bundle exec foreman export upstart /tmp -u #{user} -a #{appstage} -f ./config/foreman/#{rails_env} -l #{shared_path}/log" | |
].join(" && ") | |
sudo "[ -f /etc/init/#{appstage}.conf ] || exit 0" | |
sudo "rm -f /etc/init/#{appstage}*.conf" | |
sudo "mv /tmp/#{appstage}*.conf /etc/init/" | |
end | |
desc "Stop the services" | |
task :stop, roles: :app, except: { no_release: true } do | |
sudo "[ -f /etc/init/#{appstage}.conf ]" | |
sudo "[ $(status #{appstage} | grep -c running) -eq 1 ]" | |
sudo "stop #{appstage} || exit 0" | |
end | |
desc "Start the services" | |
task :start, roles: :app, except: { no_release: true } do | |
sudo "[ -f /etc/init/#{appstage}.conf ]" | |
sudo "[ $(status #{appstage} | grep -c running) -eq 0 ]" | |
sudo "start #{appstage}" | |
end | |
desc "Restart the services" | |
task :restart, roles: :app, except: { no_release: true } do | |
stop | |
generate_upstart | |
start | |
end | |
desc "Create database yaml in shared path" | |
task :db_configure do | |
db_config = <<-EOF | |
#{rails_env}: | |
adapter: postgresql | |
database: #{application}_#{rails_env} | |
pool: 25 | |
username: #{database_username} | |
password: #{database_password} | |
EOF | |
run "mkdir -p #{shared_path}/config" | |
put db_config, "#{shared_path}/config/database.yml" | |
end | |
desc "Make symlink for database yaml" | |
task :db_symlink do | |
run "ln -snf #{shared_path}/config/database.yml #{latest_release}/config/database.yml" | |
end | |
desc "Setup de database" | |
task :db_setup, :roles => :app do | |
run [ | |
"cd #{current_path}", | |
"bundle exec rake db:setup RAILS_ENV=#{rails_env}" | |
].join(" && ") | |
end | |
task :cold do | |
update | |
db_configure | |
db_symlink | |
db_setup | |
migrate | |
generate_upstart | |
start | |
end | |
end | |
# Before hooks. You can define your own too. | |
before "deploy", "deploy:db_symlink" | |
before "deploy:migrations", "deploy:db_symlink" | |
before "deploy:db_setup", "deploy:db_symlink" | |
# --- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment