capistrano_evrone_recipes 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ capistrano_evrone_recipes
2
+ =========================
3
+
4
+ Capistrano recipes used at evrone company
@@ -0,0 +1,33 @@
1
+ require 'logger'
2
+ require File.dirname(__FILE__) + "/util"
3
+
4
+ Capistrano::Configuration.instance(:must_exist).load do
5
+ logger.level = Capistrano::Logger::DEBUG
6
+
7
+ default_run_options[:pty] = true
8
+ ssh_options[:forward_agent] = true
9
+
10
+ set :bundle_cmd, "rbenv exec bundle"
11
+ set :rake, -> { "#{bundle_cmd} exec rake" }
12
+ set :keep_releases, 7
13
+ set :scm, "git"
14
+ set :user, "deploy"
15
+ set :deploy_via, :unshared_remote_cache
16
+ set :copy_exclude, [".git"]
17
+ set :repository_cache, -> { "#{deploy_to}/shared/#{application}.git" }
18
+
19
+ load "deploy"
20
+ require 'bundler/capistrano'
21
+
22
+ recipes_dir = File.dirname(File.expand_path(__FILE__))
23
+
24
+ load "#{recipes_dir}/recipes/crontab.rb"
25
+ load "#{recipes_dir}/recipes/foreman.rb"
26
+ load "#{recipes_dir}/recipes/deploy.rb"
27
+ load "#{recipes_dir}/recipes/login.rb"
28
+ load "#{recipes_dir}/recipes/migrate.rb"
29
+ load "#{recipes_dir}/recipes/rails.rb"
30
+ load "#{recipes_dir}/recipes/unicorn.rb"
31
+ load "#{recipes_dir}/recipes/assets.rb"
32
+ load "#{recipes_dir}/recipes/silent.rb" if ENV['CAP_SILENT_MODE']
33
+ end
@@ -0,0 +1,60 @@
1
+ _cset :asset_env, "RAILS_GROUPS=assets"
2
+ _cset :assets_prefix, "assets"
3
+ _cset :assets_role, [:web]
4
+
5
+ _cset :normalize_asset_timestamps, false
6
+
7
+ before 'deploy:finalize_update', 'deploy:assets:symlink'
8
+ after 'deploy:update_code', 'deploy:assets:precompile'
9
+
10
+ namespace :deploy do
11
+ namespace :assets do
12
+ desc <<-DESC
13
+ [internal] This task will set up a symlink to the shared directory \
14
+ for the assets directory. Assets are shared across deploys to avoid \
15
+ mid-deploy mismatches between old application html asking for assets \
16
+ and getting a 404 file not found error. The assets cache is shared \
17
+ for efficiency. If you customize the assets path prefix, override the \
18
+ :assets_prefix variable to match.
19
+ DESC
20
+ task :symlink, :roles => assets_role, :except => { :no_release => true } do
21
+ run <<-CMD
22
+ rm -rf #{latest_release}/public/#{assets_prefix} &&
23
+ mkdir -p #{latest_release}/public &&
24
+ mkdir -p #{shared_path}/assets &&
25
+ ln -s #{shared_path}/assets #{latest_release}/public/#{assets_prefix}
26
+ CMD
27
+ end
28
+
29
+ desc <<-DESC
30
+ Run the asset precompilation rake task. You can specify the full path \
31
+ to the rake executable by setting the rake variable. You can also \
32
+ specify additional environment variables to pass to rake via the \
33
+ asset_env variable. The defaults are:
34
+
35
+ set :rake, "rake"
36
+ set :rails_env, "production"
37
+ set :asset_env, "RAILS_GROUPS=assets"
38
+ DESC
39
+ task :precompile, :roles => assets_role, :except => { :no_release => true } do
40
+ CapistranoEvroneRecipes::Util.ensure_changed_remote_dirs(self, "app/assets") do
41
+ run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile"
42
+ end
43
+ end
44
+
45
+ desc <<-DESC
46
+ Run the asset clean rake task. Use with caution, this will delete \
47
+ all of your compiled assets. You can specify the full path \
48
+ to the rake executable by setting the rake variable. You can also \
49
+ specify additional environment variables to pass to rake via the \
50
+ asset_env variable. The defaults are:
51
+
52
+ set :rake, "rake"
53
+ set :rails_env, "production"
54
+ set :asset_env, "RAILS_GROUPS=assets"
55
+ DESC
56
+ task :clean, :roles => assets_role, :except => { :no_release => true } do
57
+ run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:clean"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,21 @@
1
+ require "whenever/capistrano/recipes"
2
+
3
+ set(:whenever_command) { "#{fetch(:bundle_cmd)} exec whenever" }
4
+ set(:whenever_variables) {"\"environment=#{rails_env}&path=#{current_path}&output=#{shared_path}/log/crontab.log\"" }
5
+ set(:whenever_roles) { :crontab }
6
+
7
+ namespace :crontab do
8
+ desc "Generate crontab from config/whenever.rb"
9
+ task :generate, :roles => :crontab, :on_no_matching_servers => :continue, :except => { :no_release => true } do
10
+ CapistranoEvroneRecipes::Util.ensure_changed_remote_files(self, "config/schedule.rb") do
11
+ find_and_execute_task("whenever:update_crontab")
12
+ end
13
+ end
14
+
15
+ desc "Clear crontab"
16
+ task :clear, :roles => :crontab, :on_no_matching_servers => :continue, :except => { :no_release => true } do
17
+ find_and_execute_task("whenever:clear_crontab")
18
+ end
19
+ end
20
+
21
+ after "deploy:finalize_update", 'crontab:generate'
@@ -0,0 +1,34 @@
1
+ namespace :deploy do
2
+
3
+ task :symlink_configs do
4
+ s = "cd #{shared_path}/config && "
5
+ s << "for i in `find . -type f | sed 's/^\\.\\///'` ; do "
6
+ s << "echo \"> ${i}\" ;"
7
+ s << "rm -f #{release_path}/config/${i} ;"
8
+ s << "ln -snf #{shared_path}/config/${i} #{release_path}/config/${i} ; done"
9
+ run s
10
+ end
11
+
12
+ task :start, :on_no_matching_servers => :continue, :except => { :no_release => true } do
13
+ CapistranoEvroneRecipes::Util.with_roles(self, :app) { unicorn.start }
14
+ CapistranoEvroneRecipes::Util.with_roles(self, :worker) { foreman.start }
15
+ end
16
+
17
+ task :stop, :on_no_matching_servers => :continue, :except => { :no_release => true } do
18
+ CapistranoEvroneRecipes::Util.with_roles(self, :app) { unicorn.stop }
19
+ CapistranoEvroneRecipes::Util.with_roles(self, :worker) { foreman.stop }
20
+ end
21
+
22
+ task :graceful_stop, :on_no_matching_servers => :continue, :except => { :no_release => true } do
23
+ CapistranoEvroneRecipes::Util.with_roles(self, :app) { unicorn.graceful_stop }
24
+ CapistranoEvroneRecipes::Util.with_roles(self, :worker) { foreman.stop }
25
+ end
26
+
27
+ task :restart, :on_no_matching_servers => :continue, :except => {:no_release => true} do
28
+ CapistranoEvroneRecipes::Util.with_roles(self, :app) { unicorn.restart }
29
+ CapistranoEvroneRecipes::Util.with_roles(self, :worker) { foreman.restart }
30
+ end
31
+ end
32
+
33
+ after 'deploy:finalize_update', 'deploy:symlink_configs'
34
+
@@ -0,0 +1,48 @@
1
+ _cset(:foreman_services_path) { "#{deploy_to}/services/#{release_name}" }
2
+ _cset(:foreman_cmd) { "#{fetch :bundle_cmd} exec foreman export runitu" }
3
+ _cset(:foreman_procfile) { "#{release_path}/Procfile" }
4
+ _cset(:foreman_concurency) { nil }
5
+
6
+ namespace :foreman do
7
+
8
+ desc "Restart Procfile services"
9
+ task :restart, :roles => :worker, :on_no_matching_servers => :continue, :except => { :no_release => true } do
10
+ cmd = <<-EOF
11
+ (test -L previous && readlink previous | xargs rm -rf) ;
12
+ rm -f current.new &&
13
+ ln -s #{fetch :foreman_services_path} current.new &&
14
+ rm -f previous &&
15
+ (test -L current && mv current previous) || true
16
+ && mv current.new current
17
+ EOF
18
+ cmd = cmd.gsub(/\n/, " ").gsub(/ +/, " ")
19
+ run("cd #{deploy_to}/services && #{cmd}")
20
+ end
21
+
22
+ desc "Stop services"
23
+ task :stop, :roles => :worker, :on_no_matching_servers => :continue, :except => { :no_release => true } do
24
+ cmd = "for i in `ls -1 #{deploy_to}/services/current`; do"
25
+ cmd << " sv -w 10 down #{deploy_to}/services/current/${i} ; done"
26
+ run(cmd)
27
+ end
28
+
29
+ desc "Start services"
30
+ task :start, :roles => :worker, :on_no_matching_servers => :continue, :except => { :no_release => true } do
31
+ cmd = "for i in `ls -1 #{deploy_to}/services/current`; do"
32
+ cmd << " sv -v -w 10 up #{deploy_to}/services/current/${i} ; done"
33
+ run(cmd)
34
+ end
35
+
36
+ desc "Export Procfile"
37
+ task :export, :roles => :worker, :on_no_matching_servers => :continue, :except => { :no_release => true } do
38
+ env = <<-EOF
39
+ RAILS_ENV=#{rails_env}
40
+ EOF
41
+ put(env, "#{release_path}/.env")
42
+
43
+ conc = fetch(:foreman_concurency) ? "-c #{fetch :foreman_concurency}" : ""
44
+ run "cd #{release_path} && #{fetch :foreman_cmd} #{fetch :foreman_services_path} -e #{release_path}/.env -l #{shared_path}/log -f #{fetch :foreman_procfile} --root=#{release_path} -a #{application} #{conc} > /dev/null"
45
+ end
46
+ end
47
+
48
+ after "deploy:finalize_update", "foreman:export"
@@ -0,0 +1,5 @@
1
+ desc "Login to remote host"
2
+ task :login do
3
+ hostname = find_servers_for_task(current_task).first
4
+ exec "ssh -A -l #{user} #{hostname} -t 'cd #{current_path} && ${SHELL} -l'"
5
+ end
@@ -0,0 +1,12 @@
1
+ namespace :deploy do
2
+ desc "Migrate database if has migration"
3
+ task :migrate, :roles => :db, :on_no_matching_servers => :continue, :only => {:primary => true}, :except => { :no_release => true } do
4
+ return if ENV['MIGRATE_SKIP']
5
+
6
+ CapistranoEvroneRecipes::Util.ensure_changed_remote_dirs(self, "db/migrate") do
7
+ run "cd #{release_path} && #{fetch :rake} RAILS_ENV=#{rails_env} db:migrate"
8
+ end
9
+ end
10
+ end
11
+
12
+ after "deploy:finalize_update", "deploy:migrate"
@@ -0,0 +1,19 @@
1
+ namespace :rails do
2
+ desc "Run rails console"
3
+ desc "open remote console (only on the last machine from the :app roles)"
4
+ task :console, :roles => :app do
5
+ server = find_servers_for_task(current_task).first
6
+ if server
7
+ exec "ssh -A #{server} -t 'cd #{current_path} && #{fetch :bundle_cmd} exec script/rails console #{rails_env}'"
8
+ end
9
+ end
10
+
11
+ desc "Run rails dbconsole"
12
+ desc "open remote dbconsole (only on the primary db machine)"
13
+ task :dbconsole, :roles => :db, :only => { :primary => true } do
14
+ server = find_servers_for_task(current_task).first
15
+ if server
16
+ exec "ssh -A #{server} -t 'cd #{current_path} && #{fetch :bundle_cmd} exec script/rails dbconsole #{rails_env}'"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,64 @@
1
+ require 'colored'
2
+
3
+ logger.level = Capistrano::Logger::IMPORTANT
4
+
5
+ STDOUT.sync
6
+
7
+ $silent_stack = []
8
+ $silent_stack_tm = []
9
+ $silent_stack_cur = nil
10
+ $silent_stack_skip = nil
11
+
12
+ def format_silent(name, options = {})
13
+ s = name.size
14
+ i = (70 - s).abs
15
+ #name = name.bold
16
+ if options[:bold]
17
+ name = name.gsub(/ [_a-z:]+/) do |a|
18
+ a.bold
19
+ end
20
+ end
21
+ print(name + (" " * i))
22
+ end
23
+
24
+ on :before do
25
+ $silent_stack_tm.push Time.now.to_f
26
+
27
+ name = current_task.fully_qualified_name
28
+ if $silent_stack_cur && $silent_stack_cur == $silent_stack.last
29
+ puts ""
30
+ end
31
+ $silent_stack.push name
32
+ $silent_stack_cur = name
33
+
34
+ roles = current_task.instance_eval{ @options[:roles] }
35
+
36
+ name = "#{name} [#{[roles].flatten.map(&:to_s).join(',')}]" if roles
37
+ format_silent((" " * ($silent_stack.size - 1)) + "* #{name}", :bold => true)
38
+ end
39
+
40
+ on :after do
41
+ name = current_task.fully_qualified_name
42
+ old = $silent_stack.pop
43
+ tm = $silent_stack_tm.pop
44
+ tm = Time.now.to_f - tm
45
+
46
+ spaces = $silent_stack.size
47
+ rs = "DONE".green
48
+ rs += (" %0.2fs" % tm).to_s
49
+
50
+ if $silent_stack_skip == true
51
+ rs = "SKIP".yellow
52
+ $silent_stack_skip = nil
53
+ end
54
+
55
+ if old == $silent_stack_cur
56
+ puts rs
57
+ else
58
+ format_silent((" " * (spaces)) + "...", :bold => true)
59
+ puts rs
60
+ end
61
+
62
+ $silent_stack_cur = nil
63
+ end
64
+
@@ -0,0 +1,6 @@
1
+ namespace :sphinx do
2
+ desc "Sphinx rebuild"
3
+ task :rebuild, :roles => :sphinx, :on_no_matching_servers => :continue, :except => { :no_release => true } do
4
+ run("cd #{current_path} && bundle exec rake ts:rebuild RAILS_ENV=#{rails_env}")
5
+ end
6
+ end
@@ -0,0 +1,41 @@
1
+ _cset(:unicorn_binary) { "#{fetch :bundle_cmd} exec unicorn" }
2
+ _cset(:unicorn_config) { "#{fetch :current_path}/config/unicorn.rb" }
3
+ _cset(:unicorn_pid) { "#{fetch :current_path}/tmp/pids/unicorn.pid" }
4
+
5
+ namespace :unicorn do
6
+ desc "Restart unicorn"
7
+ task :restart, :roles => :app, :on_no_matching_servers => :continue, :except => {:no_release => true} do
8
+ cmd = <<-EOF
9
+ if [ -f #{fetch :unicorn_pid} ];
10
+ then
11
+ kill -s USR2 `cat #{fetch :unicorn_pid}` &&
12
+ TIMES=1 &&
13
+ echo 'Please wait unicorn restart...' &&
14
+ sleep 1 &&
15
+ (while [ -e #{fetch :unicorn_pid}.oldbin ] ; do sleep 2; TIMES=$TIMES+2; done) &&
16
+ echo "Unicorn restart time: $TIMES sec" ;
17
+ fi
18
+ EOF
19
+ run cmd.gsub(/\n/, " ").gsub(/ +/, " ")
20
+ end
21
+
22
+ desc "Fast restart unicorn"
23
+ task :fast_restart, :roles => :app, :on_no_matching_servers => :continue, :except => {:no_release => true} do
24
+ run "test -f #{fetch :unicorn_pid} ] && kill -s USR2 `cat #{fetch :unicorn_pid}`"
25
+ end
26
+
27
+ desc "Start unicorn"
28
+ task :start, :roles => :app, :on_no_matching_servers => :continue, :except => {:no_release => true} do
29
+ run "cd #{current_path} && env #{fetch :unicorn_binary} -c #{fetch :unicorn_config} -E #{rails_env} -D"
30
+ end
31
+
32
+ desc "Stop unicorn"
33
+ task :stop, :roles => :app, :on_no_matching_servers => :continue, :except => {:no_release => true} do
34
+ run "test -f #{fetch :unicorn_pid} && kill `cat #{fetch :unicorn_pid}`"
35
+ end
36
+
37
+ desc "Graceful stop unicorn"
38
+ task :graceful_stop, :on_no_matching_servers => :continue, :roles => :app, :except => { :no_release => true } do
39
+ run "test -f #{fetch :unicorn_pid} && kill -s QUIT `cat #{fetch :unicorn_pid}`"
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ module CapistranoEvroneRecipes
2
+ class Util
3
+ class << self
4
+ def ensure_changed_remote_dirs(cap, path)
5
+ diff = if cap.previous_release
6
+ -> { cap.capture("diff -r #{cap.previous_release}/#{path} #{cap.current_release}/#{path} | wc -l").to_i }
7
+ else
8
+ -> { 1 }
9
+ end
10
+ force = ENV["FORCE"].to_i
11
+ if force > 0 || diff.call > 0
12
+ yield
13
+ else
14
+ cap.logger.info "skip because #{path} not changed"
15
+ $silent_stack_skip = true
16
+ end
17
+ end
18
+
19
+ def ensure_changed_remote_files(cap, path)
20
+ diff = if cap.previous_release
21
+ -> { cap.capture("diff -r #{cap.previous_release}/#{path} #{cap.current_release}/#{path} | wc -l").to_i }
22
+ else
23
+ -> { 1 }
24
+ end
25
+ force = ENV["FORCE"].to_i
26
+ if force > 0 || diff.call > 0
27
+ yield
28
+ else
29
+ cap.logger.info "skip because #{path} not changed"
30
+ $silent_stack_skip = true
31
+ end
32
+ end
33
+
34
+
35
+ def with_roles(cap, role)
36
+ original, hosts = ENV["HOSTS"], cap.find_servers(:roles => role).map{|i| i.host }.join(",")
37
+ return if hosts.empty?
38
+ begin
39
+ ENV["HOSTS"] = hosts
40
+ yield
41
+ ensure
42
+ ENV["HOSTS"] = original
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,13 @@
1
+ module CapistranoEvroneRecipes
2
+ class Version
3
+
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ PATCH = 0
7
+
8
+ def self.to_s
9
+ "#{MAJOR}.#{MINOR}.#{PATCH}"
10
+ end
11
+
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano_evrone_recipes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dmitry Galinsky
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: whenever
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: foreman_export_runitu
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: capistrano
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 2.13.5
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.13.5
62
+ description: Capistrano recipes used in evrone company
63
+ email: dima.exe@gmail.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - lib/capistrano_evrone_recipes/capistrano.rb
69
+ - lib/capistrano_evrone_recipes/recipes/assets.rb
70
+ - lib/capistrano_evrone_recipes/recipes/crontab.rb
71
+ - lib/capistrano_evrone_recipes/recipes/deploy.rb
72
+ - lib/capistrano_evrone_recipes/recipes/foreman.rb
73
+ - lib/capistrano_evrone_recipes/recipes/login.rb
74
+ - lib/capistrano_evrone_recipes/recipes/migrate.rb
75
+ - lib/capistrano_evrone_recipes/recipes/rails.rb
76
+ - lib/capistrano_evrone_recipes/recipes/silent.rb
77
+ - lib/capistrano_evrone_recipes/recipes/sphinx.rb
78
+ - lib/capistrano_evrone_recipes/recipes/unicorn.rb
79
+ - lib/capistrano_evrone_recipes/util.rb
80
+ - lib/capistrano_evrone_recipes/version.rb
81
+ - README.md
82
+ homepage: http://github.com/dima-exe/capistrano_evrone_recipes
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 1.8.23
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Capistrano recipes used in evrone company
106
+ test_files: []
107
+ has_rdoc: