Permalink
Browse files

Adding capistrano scripts for private cloud deployment.

  • Loading branch information...
1 parent 38f8280 commit 84f95fc4c97b4069aaf5f9448b4a8cc93d281125 Ethan Waldo committed Oct 25, 2011
Showing with 232 additions and 4 deletions.
  1. +2 −1 .gitignore
  2. +2 −0 Capfile
  3. +3 −3 Gemfile.lock
  4. +108 −0 config/deploy.rb
  5. +86 −0 config/unicorn.rb
  6. +31 −0 lib/deploy_app.rb
View
@@ -4,4 +4,5 @@ db/*.sqlite3
log/*.log
tmp/
config/*.yml
-public/assets/*
+public/assets/*
+vendor/cache
View
@@ -0,0 +1,2 @@
+load 'deploy' if respond_to?(:namespace) # cap2 differentiator
+load 'config/deploy'
View
@@ -37,15 +37,15 @@ GEM
bcrypt-ruby (3.0.0)
builder (3.0.0)
cancan (1.6.5)
- capistrano (2.8.0)
+ capistrano (2.9.0)
highline
net-scp (>= 1.0.0)
net-sftp (>= 2.0.0)
net-ssh (>= 2.0.14)
net-ssh-gateway (>= 1.1.0)
columnize (0.3.4)
date_validator (0.6.2)
- activemodel (>= 3.0.0, < 3.2.0)
+ activemodel (< 3.2.0, >= 3.0.0)
devise (1.4.5)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.0.3)
@@ -59,7 +59,7 @@ GEM
faraday (0.6.1)
addressable (~> 2.2.4)
multipart-post (~> 1.1.0)
- rack (>= 1.1.0, < 2)
+ rack (< 2, >= 1.1.0)
highline (1.6.2)
hike (1.2.1)
i18n (0.6.0)
View
@@ -0,0 +1,108 @@
+load 'lib/deploy_app.rb'
+$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
+require "rvm/capistrano"
+
+set :rvm_ruby_string, 'ruby-1.9.2-p290@raor'
+set :rvm_type, :user
+set :application, "raor"
+set :repository, "git://cloud.healthetechs.com/raor.git"
+set :rails_env, 'production'
+set :scm, :git # override default of subversion
+set :branch, 'master'
+set :use_sudo, false
+set :user, 'apache'
+set :git_enable_submodules, true
+set :ssh_options, {:forward_agent => true}
+set :default_run_options, {:shell => "sh -l"}
+set :rake, "bundle exec rake"
+set :deploy_via, :remote_cache
+set :root_path, "/var/www"
+
+
+# If you aren't deploying to /u/apps/#{application} on the target
+# servers (which is the default), you can specify the actual location
+# via the :deploy_to variable:
+set :deploy_to, "#{root_path}/#{application}"
+
+# Unicorn configuration
+set :unicorn_binary, "unicorn_rails"
+set :unicorn_config, "#{current_path}/config/unicorn.rb"
+set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid"
+
+set :production_hosts do
+ `dig -tAXFR healthetechs.com | grep production | grep A | awk '{ print $1 }'`.split("\n").map do |record|
+ record.strip[0..-2]
+ end
+end
+
+set :database_hosts do
+ `dig -tAXFR healthetechs.com | grep database | grep A | awk '{ print $1 }'`.split("\n").map do |record|
+ record.strip[0..-2]
+ end
+end
+
+#set :staging_hosts do
+# `dig -tAXFR healthetechs.com | grep staging | grep A | awk '{ print $1 }'`.split("\n").map do |record|
+# record.strip[0..-2]
+# end
+#end
+
+task :production do
+ role :app, *production_hosts
+ role :db, "#{production_hosts[0]}", :primary => true
+end
+
+task :staging do
+ role :app, *staging_hosts
+ role :db, *staging_hosts, :primary => true
+end
+
+# Setup dependencies
+after 'deploy', 'app:symlinks'
+after 'app:symlinks', 'app:bundle_rsync'
+after 'app:bundle_rsync', 'app:bundle_install'
+after "deploy", "deploy:cleanup"
+
+namespace :deploy do
+ # Overriding the built-in task to add our rollback actions
+ task :default, :roles => [:app, :web, :jobs] do
+ unless rails_env == "test"
+ transaction {
+ update
+ restart
+ }
+ end
+ end
+
+ desc "unicorn start"
+ task :start, :roles => [:app, :web] do
+ run "cd #{current_path}; bundle exec #{unicorn_binary} --daemonize --env production -c #{unicorn_config}"
+ end
+
+ desc "unicorn restart"
+ task :restart, :roles => [:app, :web] do
+ begin
+ run "kill -s USR2 `cat #{unicorn_pid}`"
+ rescue Capistrano::CommandError => e
+ puts "Rescue: #{e.class} #{e.message}"
+ puts "Rescue: It appears that unicorn is not running, starting ..."
+ run "sh #{current_path}/config/kill_server_processes unicorn"
+ run "cd #{current_path}; bundle exec #{unicorn_binary} --daemonize --env production -c #{unicorn_config}"
+ end
+ end
+end
+
+before 'deploy:migrate', 'app:update_databases'
+before 'deploy:migrate', 'app:symlinks'
+before 'deploy:migrate', 'app:bundle_rsync'
+after 'deploy:migrate', :seed
+after 'deploy:migrations', :seed
+desc "seed. for seed-fu"
+task :seed, :roles => :db, :only => {:primary => true} do
+ run "cd #{current_path}; #{rake} db:seed RAILS_ENV=#{rails_env}"
+end
+
+# useful for testing on_rollback actions
+task :raise_exc do
+ raise "STOP STOP STOP"
+end
View
@@ -0,0 +1,86 @@
+rails_env = ENV['RAILS_ENV'] || 'production'
+working_directory '/var/www/raor/current'
+
+# 16 workers and 1 master
+worker_processes (rails_env == 'production' ? 16 : 4)
+
+# Load rails+github.git into the master before forking workers
+# for super-fast worker spawn times
+preload_app true
+
+# Restart any workers that haven't responded in 30 seconds
+timeout 30
+
+# Listen on a Unix data socket
+listen '0.0.0.0:8080', :backlog => 2048
+
+stderr_path "/var/www/raor/current/log/unicorn.stderr.log"
+
+##
+# REE
+
+# http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
+#if GC.respond_to?(:copy_on_write_friendly=)
+# GC.copy_on_write_friendly = true
+#end
+
+
+before_fork do |server, worker|
+ ##
+ # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
+ # immediately start loading up a new version of itself (loaded with a new
+ # version of our app). When this new Unicorn is completely loaded
+ # it will begin spawning workers. The first worker spawned will check to
+ # see if an .oldbin pidfile exists. If so, this means we've just booted up
+ # a new Unicorn and need to tell the old one that it can now die. To do so
+ # we send it a QUIT.
+ #
+ # Using this method we get 0 downtime deploys.
+
+ old_pid = RAILS_ROOT + '/tmp/pids/unicorn.pid.oldbin'
+ if File.exists?(old_pid) && server.pid != old_pid
+ begin
+ Process.kill("QUIT", File.read(old_pid).to_i)
+ rescue Errno::ENOENT, Errno::ESRCH
+ # someone else did our job for us
+ end
+ end
+end
+
+
+after_fork do |server, worker|
+ ##
+ # Unicorn master loads the app then forks off workers - because of the way
+ # Unix forking works, we need to make sure we aren't using any of the parent's
+ # sockets, e.g. db connection
+
+ ActiveRecord::Base.establish_connection
+ #CHIMNEY.client.connect_to_server
+ # Redis and Memcached would go here but their connections are established
+ # on demand, so the master never opens a socket
+
+
+ ##
+ # Unicorn master is started as root, which is fine, but let's
+ # drop the workers to git:git
+
+ #begin
+ # uid, gid = Process.euid, Process.egid
+ # user, group = 'git', 'git'
+ # target_uid = Etc.getpwnam(user).uid
+ # target_gid = Etc.getgrnam(group).gid
+ # worker.tmp.chown(target_uid, target_gid)
+ # if uid != target_uid || gid != target_gid
+ # Process.initgroups(user, target_gid)
+ # Process::GID.change_privilege(target_gid)
+ # Process::UID.change_privilege(target_uid)
+ # end
+ #rescue => e
+ # if RAILS_ENV == 'development'
+ # STDERR.puts "couldn't change user, oh well"
+ # else
+ # raise e
+ # end
+ #end
+end
+
View
@@ -0,0 +1,31 @@
+namespace :app do
+ desc "we need a database. this helps with that."
+ task :symlinks, :roles => [:app, :web, :jobs] do
+ run "ln -fs #{shared_path}/database.yml #{release_path}/config/database.yml"
+ run "ln -fs #{shared_path}/omniauth.yml #{release_path}/config/omniauth.yml"
+ run "ln -fs #{shared_path}/vendor/cache #{release_path}/vendor/cache"
+
+ run "mkdir #{release_path}/tmp/cache"
+ end
+
+ desc "run bundle package and rsync to production"
+ task :bundle_rsync, :roles => [:app, :web, :jobs] do
+ `bundle package`
+ `scp ./vendor/cache/*.gem oneadmin@cloud.healthetechs.com:/var/lib/one/gems/raor/`
+ run "cd #{shared_path}/vendor/cache; rsync -auH rsync://cloud.healthetechs.com/gems/raor/* .;"
+ end
+
+ desc "run bundle install for gem dependencies"
+ task :bundle_install, :roles => [:app, :web, :jobs] do
+ if rails_env == "test"
+ run "cd #{current_path}; bundle install --deployment --without tools development"
+ else
+ run "cd #{current_path}; bundle install --deployment --without test development cucumber tools"
+ end
+ end
+
+ desc "update database.yml with current database host"
+ task :update_databases, :roles => [:app, :web, :jobs] do
+ run "cd #{shared_path}; sed -i '/host:/ c\\ host: #{database_hosts[0]}' database.yml;"
+ end
+end

0 comments on commit 84f95fc

Please sign in to comment.