Skip to content

Instantly share code, notes, and snippets.

@deathbob
Forked from omnifroodle/deploy.rb
Created May 6, 2010 22:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deathbob/392788 to your computer and use it in GitHub Desktop.
Save deathbob/392788 to your computer and use it in GitHub Desktop.
require 'active_support'
DEPLOY_CONFIG = YAML::load(File.open("config/deploy.yml"))
default_run_options[:pty] = true
#
# General Deployment settings
#
set :application, DEPLOY_CONFIG['application']
set :repository, DEPLOY_CONFIG['repository'] || 'master'
set :scm, :git
#
# Setting up deployment targets
#
# lets build some deployment target tasks!
# this creates the 'production' part of
# > cap production deploy
# based on the environments defined in deploy.yml
DEPLOY_CONFIG['environment'].each do |environment|
name = environment.keys.first #should only ever be one, but we'll be safe
env = environment[name]
desc "set the deploy target to #{name}"
task name.to_sym do
#setup this environment
set :environment, name
set :domain, ("#{name}.#{application}.com" || env['domain'])
set :rails_env, (env['rails_env'] || name.to_sym)
set :web_data, (env['data_dir'] || '/data/')
#user can be set at the app or environment level
set :user, env['user'] || DEPLOY_CONFIG['user']
puts fetch(:user)
if user == nil
set(:user) { Capistrano::CLI.ui.ask("User Name: ") }
end
set(:password) { Capistrano::CLI.ui.ask("Password: ") { |q| q.echo = "*" }}
#
# settings unlikely to change
#
set :deploy_to, "#{fetch :web_data}#{fetch :application}_#{fetch :environment}"
set :use_sudo, true
#create the servers for this environment
env['server'].each do |server|
servName = server.keys.first
serv = server[servName]
serv['role'].each do |job|
if job == 'db_primary'
role :db, servName, :primary => true
else
role job.to_sym, servName
end
end
end
end
end
#
# some custom actions you may want to use
#
set :package_assets, DEPLOY_CONFIG['package_assets'] || false # set to true if using the asset packager plugin
set :crontasks, DEPLOY_CONFIG['crontasks'] || false # requires a config/crontab/cron-settings
# file in your project (format is the same as a normal crontab file)
#
# settings unlikely to change
#
set :nginx_conf, "#{web_data}conf/"
set :nginx_remote_template, "#{nginx_conf}nginx.erb"
set :database_yml_template, "#{nginx_conf}database.yml.erb"
set :use_sudo, false
set(:application_db_pass) {ActiveSupport::SecureRandom.base64(12)}
ssh_options[:port] = 46559
set :deploy_via, :remote_cache
set :git_enable_submodules, 1
#
# insert custom tasks
#
after "deploy:update_code","deploy:symlink_configs"
after("deploy:update_code","deploy:package_assets") if package_assets
after("deploy:restart", "deploy:write_crontab") if crontasks
after("deploy:setup", "db:setup") unless fetch(:skip_db_setup, false)
after "deploy:setup", "nginx:configure"
before "deploy:restart", "nginx:configure"
before "deploy:start", "nginx:configure"
after "deploy", "deploy:cleanup"
#
# Dynamic nginx config files
#
# credit: http://www.subreview.com/articles/6
namespace(:nginx) do
task :configure do
nginx_template=<<-EOF
# File generated on <%=Time.now().strftime("%d %b %y")%>
<% if redirect %>
server {
listen 80;
client_max_body_size 3M;
server_name <%=redirect %> ;
rewrite ^/(.*) http://<%=domain %> permanent;
}
<% end %>
server {
listen 80;
server_name <%=domain %>;
client_max_body_size 3M;
rails_env <%= rails_env %>;
access_log <%=deploy_to%>/shared/log/access.log;
error_log <%=deploy_to%>/shared/log/error.log;
root <%=deploy_to%>/current/public/;
index index.html;
passenger_enabled on;
}
EOF
# run the template
template_file(nginx_template,nginx_remote_config)
#add a symlink into sites enabled
run "ln -s -f #{nginx_conf}sites-available/#{application}_#{rails_env} #{nginx_conf}sites-enabled/#{application}_#{rails_env}"
run "sudo /etc/init.d/nginx reload"
end
end
namespace(:deploy) do
task :symlink_configs, :roles => :app, :except => {:no_symlink => true} do
run <<-CMD
cd #{release_path} &&
ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml &&
ln -nfs #{shared_path}/system #{release_path}/public/system &&
ln -s #{shared_path}/news_releases #{release_path}/public/news_releases
CMD
end
task :restart do
run "touch #{current_path}/tmp/restart.txt"
end
task :write_crontab, :roles => :app do
puts "Installing server-specific crontab."
run("cd #{deploy_to}/current/config/crontab; crontab cron-settings")
end
desc "install gems listed in environment.rb"
task :install_gems do
run "cd #{current_path} && rake gems:install RAILS_ENV=production"
end
end
namespace(:monitor) do
desc "Tail the Rails production log for this environment"
task :tail_production_logs, :roles => :app do
run "tail -f #{shared_path}/log/production.log" do |channel, stream, data|
puts # for an extra line break before the host name
puts "#{channel[:server]} -> #{data}"
break if stream == :err
end
end
end
load :file => "config/my_deploy_tasks.rb" if Dir.entries('.').detect{|f| f.match 'my_deploy_tasks.rb'}
namespace :db do
desc "Creates a new database and user, and grants the user rights to the database. Creates the database.yml configuration file in shared path."
task :setup, :except => { :no_release => true } do
database_template=<<-EOF
# File generated on <%=Time.now().strftime("%d %b %y")%>
<%= rails_env %>:
adapter: mysql
encoding: utf8
database: <%= application %>_<%= rails_env[0,4] %>
pool: 5
username: <%= application %>_<%= rails_env[0,4] %>
password: <%= application_db_pass %>
socket: /var/run/mysqld/mysqld.sock
EOF
run "mkdir -p #{shared_path}/db"
run "mkdir -p #{shared_path}/config"
template_file(database_template,"#{shared_path}/config/database.yml")
#create the database and user base on the application and password
run "/data/scripts/user_and_db.rb #{application}_#{rails_env[0,4]} #{application_db_pass}"
end
desc "Updates the symlink for database.yml file to the just deployed release."
task :symlink, :except => { :no_release => true } do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
end
#
# Get the template as a string,
# parse it, and place the new file on the server
#
def template_file(template,remote_file_to_put)
require 'erb' #render not available in Capistrano 2
buffer= ERB.new(template).result(binding) # parse it
put buffer,remote_file_to_put # put the result
end
application: "example"
user: 'webmin'
package_assets: no
crontasks: no
environment:
- staging:
data_dir: '/data/'
#setting user here overrides
#user: 'omnifroodle'
domain: "www.example_staging.inmunited.com"
redirect: "example_staging.inmunited.com *.example_staging.inmunited.com"
server: #
- 127.0.0.1:
role:
- app
- web
- db_primary
- production:
data_dir: '/data/www/'
#setting user here overrides
#user: 'omnifroodle'
domain: "www.example.com"
redirect: "example.com *.example.com"
server:
- 127.0.0.2:
role:
- app
- web
- db_primary
- 127.0.0.3: #example of a second production server
role:
- db
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment