ricodigo-capistrano-recipes 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,65 @@
1
+ rails_root = '<%= "#{deploy_to}/current" %>'
2
+ rails_env = '<%= environment %>'
3
+ pid_file = '<%= unicorn_pid %>'
4
+ socket_file= '<%= unicorn_socket %>'
5
+ log_file = '<%= deploy_to %>/current/log/unicorn.log'
6
+ username = '<%= unicorn_user %>'
7
+ group = '<%= unicorn_group %>'
8
+ old_pid = pid_file + '.oldbin'
9
+
10
+
11
+ working_directory rails_root
12
+
13
+ timeout <%= unicorn_workers_timeout %>
14
+
15
+ worker_processes <%= unicorn_workers %>
16
+
17
+ # Listen on a Unix data socket
18
+ listen socket_file, :backlog => 1024
19
+ pid pid_file
20
+
21
+ stderr_path log_file
22
+ stdout_path log_file
23
+
24
+ preload_app true
25
+
26
+ GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)
27
+
28
+ before_fork do |server, worker|
29
+ if File.exists?(old_pid) && server.pid != old_pid
30
+ pid = File.read(old_pid).to_i
31
+ begin
32
+ Process.kill("QUIT", pid)
33
+ Process.kill(0, pid)
34
+ Process.wait
35
+ rescue Errno::ECHILD, Errno::ESRCH => e
36
+ $stderr.puts ">> Process #{pid} has stopped"
37
+ rescue Errno::ENOENT => e
38
+ $stderr.puts ">> Error killing previous instance. #{e.message}"
39
+ # someone else did our job for us
40
+ end
41
+ end
42
+ end
43
+
44
+
45
+ after_fork do |server, worker|
46
+ begin
47
+ uid, gid = Process.euid, Process.egid
48
+
49
+ target_uid = File.stat(Rails.root).uid
50
+ user = Etc.getpwuid(target_uid).name
51
+
52
+ target_gid = File.stat(Rails.root).gid
53
+ group = Etc.getgrgid(target_gid).name
54
+
55
+ worker.tmp.chown(target_uid, target_gid)
56
+ if uid != target_uid || gid != target_gid
57
+ Process.initgroups(user, target_gid)
58
+ Process::GID.change_privilege(target_gid)
59
+ Process::UID.change_privilege(target_uid)
60
+ end
61
+ rescue => e
62
+ STDERR.puts "cannot change privileges on #{Rails.env} environment"
63
+ STDERR.puts " #{e}"
64
+ end
65
+ end
data/lib/helpers.rb ADDED
@@ -0,0 +1,88 @@
1
+ # =========================================================================
2
+ # These are helper methods that will be available to your recipes.
3
+ # =========================================================================
4
+
5
+ # automatically sets the environment based on presence of
6
+ # :stage (multistage gem), :rails_env, or RAILS_ENV variable; otherwise defaults to 'production'
7
+ def environment
8
+ if exists?(:stage)
9
+ stage
10
+ elsif exists?(:rails_env)
11
+ rails_env
12
+ elsif(ENV['RAILS_ENV'])
13
+ ENV['RAILS_ENV']
14
+ else
15
+ "production"
16
+ end
17
+ end
18
+
19
+ def is_using_nginx
20
+ is_using('nginx',:web_server)
21
+ end
22
+
23
+ def is_using_passenger
24
+ is_using('passenger',:app_server)
25
+ end
26
+
27
+ def is_using_unicorn
28
+ is_using('unicorn',:app_server)
29
+ end
30
+
31
+ def is_app_monitored?
32
+ is_using('bluepill', :monitorer)
33
+ end
34
+
35
+ def is_using(something, with_some_var)
36
+ exists?(with_some_var.to_sym) && fetch(with_some_var.to_sym).to_s.downcase == something
37
+ end
38
+
39
+ # Path to where the generators live
40
+ def templates_path
41
+ expanded_path_for('../generators')
42
+ end
43
+
44
+ def docs_path
45
+ expanded_path_for('../doc')
46
+ end
47
+
48
+ def expanded_path_for(path)
49
+ e = File.join(File.dirname(__FILE__),path)
50
+ File.expand_path(e)
51
+ end
52
+
53
+ def parse_config(file)
54
+ require 'erb' #render not available in Capistrano 2
55
+ template=File.read(file) # read it
56
+ return ERB.new(template).result(binding) # parse it
57
+ end
58
+
59
+ # =========================================================================
60
+ # Prompts the user for a message to agree/decline
61
+ # =========================================================================
62
+ def ask(message, default=true)
63
+ Capistrano::CLI.ui.agree(message)
64
+ end
65
+
66
+ # Generates a configuration file parsing through ERB
67
+ # Fetches local file and uploads it to remote_file
68
+ # Make sure your user has the right permissions.
69
+ def generate_config(local_file,remote_file)
70
+ temp_file = '/tmp/' + File.basename(local_file)
71
+ buffer = parse_config(local_file)
72
+ File.open(temp_file, 'w+') { |f| f << buffer }
73
+ upload temp_file, remote_file, :via => :scp
74
+ `rm #{temp_file}`
75
+ end
76
+
77
+ # =========================================================================
78
+ # Executes a basic rake task.
79
+ # Example: run_rake log:clear
80
+ # =========================================================================
81
+ def run_rake(task)
82
+ run "cd #{current_path} && rake #{task} RAILS_ENV=#{environment}"
83
+ end
84
+
85
+
86
+ def rvmsudo(task)
87
+ run "cd #{current_path} && rvmsudo #{task}"
88
+ end
@@ -0,0 +1,68 @@
1
+ Capistrano::Configuration.instance.load do
2
+ # User settings
3
+ set :user, 'app' unless exists?(:user)
4
+ set :group,'app' unless exists?(:group)
5
+
6
+ # Server settings
7
+ set :app_server, :unicorn unless exists?(:app_server)
8
+ set :web_server, :nginx unless exists?(:web_server)
9
+ set :runner, user unless exists?(:runner)
10
+ set :application_port, 80 unless exists?(:application_port)
11
+
12
+ set :application_uses_ssl, true unless exists?(:application_uses_ssl)
13
+ set :application_port_ssl, 443 unless exists?(:application_port_ssl)
14
+
15
+ # Database settings
16
+ set :database, :mongodb unless exists?(:database)
17
+
18
+ # SCM settings
19
+ set :scm, :git
20
+ set :branch, 'master' unless exists?(:branch)
21
+ set :deploy_to, "/home/#{user}/rails/#{application}"
22
+ set :deploy_via, :checkout
23
+ set :keep_releases, 3
24
+ set :run_method, :run
25
+ set :git_enable_submodules, true
26
+ set :git_shallow_clone, 1
27
+ set :rails_env, 'production' unless exists?(:rails_env)
28
+
29
+ # Git settings for capistrano
30
+ default_run_options[:pty] = true
31
+ ssh_options[:forward_agent] = true
32
+
33
+ # RVM settings
34
+ set :using_rvm, true unless exists?(:using_rvm)
35
+
36
+ if using_rvm
37
+ $:.unshift(File.expand_path('./lib', ENV['rvm_path'])) # Add RVM's lib directory to the load path.
38
+ require "rvm/capistrano" # Load RVM's capistrano plugin.
39
+
40
+ # Sets the rvm to a specific version (or whatever env you want it to run in)
41
+ set :rvm_ruby_string, '1.9.2' unless exists?(:rvm_ruby_string)
42
+ end
43
+
44
+ # Daemons settings
45
+ # The unix socket that unicorn will be attached to.
46
+ # Also, nginx will upstream to this guy.
47
+ # The *nix place for socks is /var/run, so we should probably put it there
48
+ # Make sure the runner can access this though.
49
+ set :sockets_path, "/var/run/#{application}" unless exists?(:sockets_path)
50
+
51
+ # Just to be safe, put the pid somewhere that survives deploys. shared/pids is
52
+ # a good choice as any.
53
+ set(:pids_path) { File.join(shared_path, "pids") } unless exists?(:pids_path)
54
+
55
+ set :monitorer, 'bluepill' unless exists?(:monitorer)
56
+
57
+ # Application settings
58
+ set :shared_dirs, %w(config config/pills uploads backup bundle tmp sockets pids log system) unless exists?(:shared_dirs)
59
+
60
+ namespace :app do
61
+ task :setup, :roles => :app do
62
+ commands = shared_dirs.map do |path|
63
+ "if [ ! -d '#{path}' ]; then mkdir -p #{path}; fi;"
64
+ end
65
+ run "cd #{shared_path}; #{commands.join(' ')}"
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,66 @@
1
+ Capistrano::Configuration.instance.load do
2
+ set(:bluepill_local_config) { "#{templates_path}/app.bluepill.erb" } unless exists?(:nginx_local_config)
3
+ set(:bluepill_remote_config) { "#{shared_path}/config/pills/#{application}.pill" } unless exists?(:nginx_remote_config)
4
+
5
+ namespace :bluepill do
6
+ desc "|capistrano-recipes| Parses and uploads nginx configuration for this app."
7
+ task :setup, :roles => :app , :except => { :no_release => true } do
8
+ generate_config(bluepill_local_config, bluepill_remote_config)
9
+ end
10
+
11
+ desc "|capistrano-recipes| Install the bluepill monitoring tool"
12
+ task :install, :roles => [:app] do
13
+ sudo "gem install bluepill"
14
+ end
15
+
16
+ desc "|capistrano-recipes| Stop processes that bluepill is monitoring and quit bluepill"
17
+ task :quit, :roles => [:app] do
18
+ args = exists?(:options) ? options : ''
19
+ begin
20
+ rvmsudo "bluepill stop #{args}"
21
+ rescue
22
+ puts "Bluepill was unable to finish gracefully all the process"
23
+ ensure
24
+ rvmsudo "bluepill quit"
25
+ end
26
+ end
27
+
28
+ desc "|capistrano-recipes| Load the pill from {your-app}/config/pills/{app-name}.pill"
29
+ task :init, :roles =>[:app] do
30
+ rvmsudo "bluepill load #{shared_path}/config/pills/#{application}.pill"
31
+ end
32
+
33
+ desc "|capistrano-recipes| Starts your previous stopped pill"
34
+ task :start, :roles =>[:app] do
35
+ args = exists?(:options) ? options : ''
36
+ app = exists?(:app) ? app : application
37
+ rvmsudo "bluepill #{app} start #{args}"
38
+ end
39
+
40
+ desc "|capistrano-recipes| Stops some bluepill monitored process"
41
+ task :stop, :roles =>[:app] do
42
+ args = exists?(:options) ? options : ''
43
+ app = exists?(:app) ? app : application
44
+ rvmsudo "bluepill #{app} stop #{args}"
45
+ end
46
+
47
+ desc "|capistrano-recipes| Restarts the pill from {your-app}/config/pills/{app-name}.pill"
48
+ task :restart, :roles =>[:app] do
49
+ args = exists?(:options) ? options : ''
50
+ app = exists?(:app) ? app : application
51
+ rvmsudo "bluepill #{app} restart #{args}"
52
+ end
53
+
54
+ desc "|capistrano-recipes| Prints bluepills monitored processes statuses"
55
+ task :status, :roles => [:app] do
56
+ args = exists?(:options) ? options : ''
57
+ app = exists?(:app) ? app : application
58
+ rvmsudo "bluepill #{app} status #{args}"
59
+ end
60
+ end
61
+
62
+ after 'deploy:setup' do
63
+ bluepill.install if Capistrano::CLI.ui.agree("Do you want to install the bluepill monitor? [Yn]")
64
+ bluepill.setup if Capistrano::CLI.ui.agree("Create bluepill configuration file? [Yn]")
65
+ end if is_using('bluepill', :monitorer)
66
+ end
@@ -0,0 +1,14 @@
1
+ Capistrano::Configuration.instance.load do
2
+ namespace :bundler do
3
+ desc "|capistrano-recipes| Installs bundler gem to your server"
4
+ task :setup, :roles => :app do
5
+ run "if ! gem list | grep --silent -e 'bundler'; then #{try_sudo} gem uninstall bundler; #{try_sudo} gem install --no-rdoc --no-ri bundler; fi"
6
+ end
7
+
8
+ desc "|capistrano-recipes| Runs bundle install on the app server (internal task)"
9
+ task :install, :roles => :app, :except => { :no_release => true } do
10
+ run "cd #{current_path} && bundle install --deployment --without=development test"
11
+ end
12
+ end
13
+ end
14
+
data/lib/recipes/db.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'erb'
2
+
3
+ Capistrano::Configuration.instance.load do
4
+ namespace :db do
5
+ namespace :mongodb do
6
+ desc <<-EOF
7
+ |capistrano-recipes| Performs a compressed database dump. \
8
+ WARNING: This locks your tables for the duration of the mongodump.
9
+ Don't run it madly!
10
+ EOF
11
+ task :dump, :roles => :db, :only => { :primary => true } do
12
+ prepare_from_yaml
13
+ run "mongodump -u #{db_user} -p #{db_pass} -h #{db_host} --port #{db_port} -d #{db_name} #{db_backup_path}" do |ch, stream, out|
14
+ puts out
15
+ end
16
+ end
17
+
18
+ desc "|capistrano-recipes| Restores the database from the latest compressed dump"
19
+ task :restore, :roles => :db, :only => { :primary => true } do
20
+ prepare_from_yaml
21
+ run "mongorestore --drop -d #{db_name} #{db_backup_path}/#{db_name}" do |ch, stream, out|
22
+ puts out
23
+ end
24
+ end
25
+
26
+ desc "|capistrano-recipes| Downloads the compressed database dump to this machine"
27
+ task :fetch_dump, :roles => :db, :only => { :primary => true } do
28
+ prepare_from_yaml
29
+ download db_remote_file, db_local_file, :via => :scp
30
+ end
31
+
32
+ # Sets database variables from remote database.yaml
33
+ def prepare_from_yaml
34
+ set(:db_backup_path) { "#{shared_path}/backup/" }
35
+ set(:db_local_file) { "tmp/#{db_file}" }
36
+ set(:db_user) { db_config[rails_env]["username"] }
37
+ set(:db_pass) { db_config[rails_env]["password"] }
38
+ set(:db_host) { db_config[rails_env]["host"] }
39
+ set(:db_name) { db_config[rails_env]["database"] }
40
+ end
41
+
42
+ def db_config
43
+ @db_config ||= fetch_db_config
44
+ end
45
+
46
+ def fetch_db_config
47
+ require 'yaml'
48
+ file = capture "cat #{shared_path}/config/mongoid.yml"
49
+ db_config = YAML.load(file)
50
+ end
51
+ end
52
+
53
+ desc "|capistrano-recipes| Create mongoid.yml in shared path with settings for current stage and test env"
54
+ task :setup do
55
+ set(:db_host) { Capistrano::CLI.ui.ask("Enter #{environment} database host:") {|q|q.default = "localhost"} }
56
+ set(:db_port) { Capistrano::CLI.ui.ask("Enter #{environment} database port:", Integer){|q| q.default = 27017 } }
57
+ set(:db_user) { Capistrano::CLI.ui.ask "Enter #{environment} database username:" }
58
+ set(:db_pass) { Capistrano::CLI.password_prompt "Enter #{environment} database password:" }
59
+ set(:db_safe_mode) { Capistrano::CLI.ui.agree "Enable safe mode on #{environment} database? [Yn]:" }
60
+
61
+ db_config = ERB.new <<-EOF
62
+ defaults: &defaults
63
+ host: #{db_host}
64
+ port: #{db_port}
65
+ <% if db_user && !db_user.empty? %>
66
+ username: #{db_user}
67
+ password: #{db_pass}
68
+ <% end %>
69
+ autocreate_indexes: false
70
+ allow_dynamic_fields: true
71
+ include_root_in_json: false
72
+ parameterize_keys: true
73
+ persist_in_safe_mode: #{db_safe_mode}
74
+ raise_not_found_error: true
75
+ reconnect_time: 3
76
+
77
+ development:
78
+ <<: *defaults
79
+ database: #{application}-development
80
+
81
+ test:
82
+ <<: *defaults
83
+ database: #{application}-test
84
+
85
+ production:
86
+ <<: *defaults
87
+ database: #{application}-production
88
+ EOF
89
+
90
+ put db_config.result(binding), "#{shared_path}/config/mongoid.yml"
91
+ end
92
+ end
93
+
94
+ after "deploy:setup" do
95
+ db.setup if Capistrano::CLI.ui.agree("Create mongoid.yml in app's shared path? [Yn]")
96
+ end
97
+ end
@@ -0,0 +1,65 @@
1
+ Capistrano::Configuration.instance.load do
2
+ set :shared_children, %w(system log pids config)
3
+
4
+ namespace :deploy do
5
+ desc "|capistrano-recipes| Deploy it, github-style."
6
+ task :default, :roles => :app, :except => { :no_release => true } do
7
+ update
8
+ restart
9
+ end
10
+
11
+ desc "|capistrano-recipes| Destroys everything"
12
+ task :seppuku, :roles => :app, :except => { :no_release => true } do
13
+ run "rm -rf #{current_path}; rm -rf #{shared_path}"
14
+ end
15
+
16
+ desc "|capistrano-recipes| Create shared dirs"
17
+ task :setup_dirs, :roles => :app, :except => { :no_release => true } do
18
+ commands = shared_dirs.map do |path|
19
+ "mkdir -p #{shared_path}/#{path}"
20
+ end
21
+ run commands.join(" && ")
22
+ end
23
+
24
+ desc "|capistrano-recipes| Uploads your local config.yml to the server"
25
+ task :configure, :roles => :app, :except => { :no_release => true } do
26
+ generate_config('config/config.yml', "#{shared_path}/config/config.yml")
27
+ end
28
+
29
+ desc "|capistrano-recipes| Setup a GitHub-style deployment."
30
+ task :setup, :roles => :app, :except => { :no_release => true } do
31
+ run "rm -rf #{current_path}"
32
+ setup_dirs
33
+ run "git clone #{repository} #{current_path}"
34
+ end
35
+
36
+ desc "|capistrano-recipes| Update the deployed code."
37
+ task :update_code, :roles => :app, :except => { :no_release => true } do
38
+ run "cd #{current_path}; git fetch origin; git reset --hard #{branch}"
39
+ end
40
+
41
+ desc "|capistrano-recipes| Alias for symlinks:make"
42
+ task :symlink, :roles => :app, :except => { :no_release => true } do
43
+ symlinks.make
44
+ end
45
+
46
+ desc "|capistrano-recipes| Remote run for rake db:seed"
47
+ task :migrate, :roles => :app, :except => { :no_release => true } do
48
+ run "cd #{current_path}; bundle exec rake RAILS_ENV=#{rails_env} db:seed"
49
+ end
50
+
51
+ desc "|capistrano-recipes| [Obsolete] Nothing to cleanup when using reset --hard on git"
52
+ task :cleanup, :roles => :app, :except => { :no_release => true } do
53
+ #nothing to cleanup, we're not working with 'releases'
54
+ puts "Nothing to cleanup, yay!"
55
+ end
56
+
57
+ namespace :rollback do
58
+ desc "|capistrano-recipes| Rollback , :except => { :no_release => true }a single commit."
59
+ task :default, :roles => :app, :except => { :no_release => true } do
60
+ set :branch, "HEAD^"
61
+ deploy.default
62
+ end
63
+ end
64
+ end
65
+ end