-
-
Save constantine-nikolaou/806601 to your computer and use it in GitHub Desktop.
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
# capistrano deployment | |
require "bundler/capistrano" | |
require "capistrano/ext/multistage" | |
set :stages, %w(canary production) | |
set :default_stage, "canary" | |
set :application, "lolcats" | |
set :deploy_to, "/srv/#{application}" | |
set :repository, "[email protected]:/lolcats/#{application}.git" | |
set :branch, "master" # can be overriden by set_branch | |
set :scm, "git" | |
set :git_enable_submodules, 1 | |
set :deploy_via, :checkout | |
ssh_options[:forward_agent] = true | |
set :migrate_target, :latest | |
set :keep_releases, 10 | |
set :use_sudo, false | |
# Deployment hooks | |
after "multistage:ensure", "set_branch" | |
before "deploy:update_code", "tag_release" | |
after "bundle:install", "deploy:migrate" | |
before "deploy:migrate", "memcached:flush_if_pending_migrations" | |
after "deploy:restart", "deploy:cleanup" | |
after "deploy:restart", "delayed_job:restart" | |
# BRANCH=experimental cap canary deploy | |
task :set_branch do | |
set :branch, (ENV["BRANCH"] && fetch(:stage) != :production) ? ENV["BRANCH"].to_s : fetch(:stage).to_s | |
set :rails_env, stage | |
end | |
task :tag_release do | |
system "cd #{File.dirname(__FILE__)}/.. && ./script/tag_release #{stage} #{release_name}" | |
raise "Error running script/tag_release" unless $? == 0 | |
end | |
namespace :deploy do | |
desc "Create shared directories, setup symlinks and adjust permissions" | |
task :finalize_update, :except => { :no_release => true } do | |
run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true) | |
run <<-CMD | |
rm -rf #{latest_release}/log && | |
rm -rf #{latest_release}/tmp && | |
mkdir -p #{latest_release}/public && | |
mkdir -p #{shared_path}/log && | |
mkdir -p #{shared_path}/tmp/pids && | |
mkdir -p #{shared_path}/tmp/sockets && | |
mkdir -p #{shared_path}/.bundle && | |
mkdir -p #{shared_path}/vendor/bundler_gems | |
CMD | |
run <<-CMD | |
ln -s #{shared_path}/tmp #{latest_release}/tmp && | |
ln -s #{shared_path}/log #{latest_release}/log && | |
ln -s #{shared_path}/.bundle #{latest_release}/.bundle && | |
ln -s #{shared_path}/vendor/bundler_gems #{latest_release}/vendor/bundler_gems && | |
cd #{latest_release}/public && | |
ln -s javascripts javascripts.#{real_revision} && | |
ln -s stylesheets stylesheets.#{real_revision} && | |
ln -s images images.#{real_revision} && | |
cd #{shared_path} && rm -f html && ln -s app/public html | |
CMD | |
if fetch(:normalize_asset_timestamps, true) | |
stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S") | |
asset_paths = %w(images stylesheets javascripts).map { |p| "#{latest_release}/public/#{p}" }.join(" ") | |
run "find #{asset_paths} -exec touch -t #{stamp} {} ';'; true", :env => { "TZ" => "UTC" } | |
end | |
end | |
# Reloading the app server(s) | |
# For now, execute both unicorn *and* passenger restart actions for back-compat | |
desc "Restart the application" | |
task :restart, :roles => :app, :except => { :no_release => true } do | |
# deploy::restart_passenger | |
deploy::restart_unicorn | |
end | |
desc "Restart Unicorn-powered Application (via USR2 signal)" | |
task :restart_unicorn, :roles => :app, :except => { :no_release => true } do | |
unicorn::restart | |
end | |
desc "Restart Passenger-powered Application (via 'touch tmp/restart.txt')" | |
task :restart_passenger, :roles => :app, :except => { :no_release => true } do | |
run "mkdir -p #{current_path}/tmp && touch #{current_path}/tmp/restart.txt" | |
end | |
# Database migrations | |
desc "Run the db:migrate rake task" | |
task :migrate, :roles => :db, :only => { :primary => true } do | |
rake = fetch(:rake, "rake") | |
rails_env = fetch(:stage, "production") | |
directory = case migrate_target.to_sym | |
when :current then current_path | |
when :latest then current_release | |
else raise ArgumentError, "unknown migration target #{migrate_target.inspect}" | |
end | |
run "cd #{directory}; RAILS_ENV=#{rails_env} #{rake} db:migrate" | |
end | |
end | |
# Bring the application offline using system/maintenance.html, which gets served up by nginx/apache | |
namespace :downtime do | |
desc "Installs the maintenance.html file into public" | |
task :start, :roles => :app, :except => { :no_release => true } do | |
run "cd #{current_release} && RAILS_ENV=#{rails_env} /usr/bin/rake static_ads:generate[#{current_path}/public]" | |
end | |
desc "Removes the maintenance.html file from public" | |
task :end, :roles => :app, :except => { :no_release => true } do | |
run "cd #{current_release} && RAILS_ENV=#{rails_env} /usr/bin/rake static_ads:delete[#{current_path}/public]" | |
end | |
end | |
# Pay attention to various logfiles on all the remote servers | |
namespace :tail do | |
desc "tail rails application logs" | |
task :app, :roles => :app do | |
tail_logs("#{shared_path}/log/#{rails_env}.log #{shared_path}/log/unicorn.stderr.log") | |
end | |
desc "tail unicorn stderr log" | |
task :unicorn, :roles => :app do | |
tail_logs("#{shared_path}/log/unicorn.stderr.log") | |
end | |
desc "tail nginx access logs" | |
task :web, :roles => :app do | |
tail_logs("/var/log/nginx/#{application}-access.log") | |
end | |
desc "tail nginx error logs" | |
task :errors, :roles => :app do | |
tail_logs("/var/log/nginx/#{application}-error.log /var/log/nginx/error.log") | |
end | |
desc "tail delayed_job worker logs" | |
task :jobs, :roles => :worker do | |
tail_logs("#{shared_path}/log/delayed_job.log") | |
end | |
end | |
def tail_logs(files) | |
set :user, ENV['USER'] | |
run("tail -n0 -f #{files}") do |channel, stream, data| | |
puts # for an extra line break before the host name | |
print "#{channel[:host]}: #{data}" | |
end | |
end | |
namespace :delayed_job do | |
desc "Start delayed job workers" | |
task :start, :roles => :worker do | |
worker_count = (stage == :canary ? 1 : 4) | |
run "cd #{current_path} && RAILS_ENV=#{rails_env} NEWRELIC_DISPATCHER=delayed_job script/delayed_job start -n #{worker_count}" | |
end | |
desc "Stop delayed job workers" | |
task :stop, :roles => :worker do | |
run "cd #{current_path} && RAILS_ENV=#{rails_env} NEWRELIC_DISPATCHER=delayed_job script/delayed_job stop" | |
end | |
desc "Restart delayed jobs (in the background)" | |
task :restart, :roles => :worker do | |
delayed_job::stop | |
delayed_job::start | |
end | |
end | |
namespace :unicorn do | |
desc "Start all unicorns using /etc/init.d/unicorn" | |
task :start, :roles => :app do | |
run "invoke-rc.d unicorn start" | |
end | |
desc "Stop all unicorns using /etc/init.d/unicorn" | |
task :stop, :roles => :app do | |
run "invoke-rc.d unicorn stop" | |
end | |
desc "Restart running unicorns using SIGUSR2 (NOT /etc/init.d/unicorn)" | |
task :restart, :roles => :app do | |
run <<-CMD | |
if [ -e #{current_path}/tmp/pids/unicorn.pid ] && kill -0 $(cat #{current_path}/tmp/pids/unicorn.pid); then \ | |
echo 'Upgrading Unicorn...'; \ | |
kill -USR2 $(cat #{current_path}/tmp/pids/unicorn.pid); \ | |
else \ | |
echo 'Unicorn not running! Starting manually...'; \ | |
cd #{current_path}; \ | |
rm -f tmp/pids/unicorn.pid; \ | |
/usr/bin/bundle exec unicorn -c config/unicorn.rb -E #{rails_env} -D #{current_path}/config.ru; \ | |
fi | |
CMD | |
end | |
desc "Display unicorn statuses" | |
task :status, :roles => :app do | |
run("ps auxf | egrep '([u]nicorn|USER)' | egrep -v '(tail|grep)'") | |
end | |
end | |
namespace :chef do | |
desc "chef reprovision all of the servers" | |
task :provision do | |
run "cd /var/local/spark && rake provision:run" | |
end | |
desc "tail the chef_client logs" | |
task :log do | |
tail_logs("/var/log/chef_client.log") | |
end | |
end | |
namespace :memcached do | |
desc "Flush memcached" | |
task :flush, :roles => [:app] do | |
run("cd #{current_release} && RAILS_ENV=#{rails_env} /usr/bin/rake memcached:flush") | |
end | |
desc "Flush memcached if there are any pending migrations (installs hook, run before db:migrate)" | |
task :flush_if_pending_migrations, :roles => [:app] do | |
output = capture("cd #{current_release} && RAILS_ENV=#{rails_env} /usr/bin/rake db:pending_migration_count") | |
count = /(\d+) pending migrations/.match(output) | |
if count[0] && count[0].to_i > 0 | |
puts "#{count[0].to_i} migrations will be run! Installing memcached:flush hook" | |
after "deploy:migrate", "memcached:flush" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment