capistrano-runit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1 @@
1
+ TODO: Write README!
@@ -0,0 +1,12 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "capistrano-runit"
3
+ s.version = "1.0.0"
4
+ s.summary = "Useful deployment recipes."
5
+ s.homepage = "http://github.com/antage/capistrano-runit"
6
+ s.author = "Anton Ageev"
7
+ s.email = "antage@gmail.com"
8
+ s.files = `git ls-files`.split
9
+ s.add_dependency "capistrano", ">= 2.0.0"
10
+ end
11
+
12
+ # vim:ts=2 sw=2 ft=ruby
@@ -0,0 +1,13 @@
1
+ Capistrano::Configuration.instance(true).load do
2
+ _cset :runit_dir, defer { "#{deploy_to}/runit" }
3
+
4
+ namespace :runit do
5
+ desc "Setup runit directories"
6
+ task :setup, :roles => :app do
7
+ run "[ -d #{runit_dir}/.env ] || mkdir -p #{runit_dir}/.env"
8
+ run "echo $HOME > #{runit_dir}/.env/HOME"
9
+ run "[ -d #{runit_dir}/available ] || mkdir -p #{runit_dir}/available"
10
+ run "[ -d #{runit_dir}/enabled ] || mkdir -p #{runit_dir}/enabled"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ Capistrano::Configuration.instance(true).load do
2
+ _cset :runit_delayed_job_service_name, "delayed_job"
3
+ _cset :runit_delayed_job_template, File.expand_path(File.join(File.dirname(__FILE__), "../templates/run-delayed_job.erb"))
4
+ _cset :runit_delayed_job_command, "./script/delayed_job"
5
+
6
+ namespace :runit do
7
+ namespace :delayed_job do
8
+ desc "Setup delayed_job runit-service"
9
+ task :setup, :roles => :app do
10
+ run "[ -d #{runit_dir}/available/#{runit_delayed_job_service_name} ] || mkdir -p #{runit_dir}/available/#{runit_delayed_job_service_name}"
11
+ template = File.read(runit_delayed_job_template)
12
+ erb_template = ERB.new(template)
13
+ servers = find_servers_for_task(current_task)
14
+ servers.each do |server|
15
+ put erb_template.result(binding), "#{runit_dir}/available/#{runit_delayed_job_service_name}/run", :mode => 0755, :hosts => server.host
16
+ end
17
+ find_and_execute_task "runit:delayed_job:enable"
18
+ end
19
+
20
+ desc "Enable delayed_job runit-service"
21
+ task :enable, :roles => :app do
22
+ run "cd #{runit_dir}/enabled && [ -h ./#{runit_delayed_job_service_name} ] || ln -sf ../available/#{runit_delayed_job_service_name} ."
23
+ end
24
+
25
+ desc "Disable delayed_job runit-service"
26
+ task :disable, :roles => :app do
27
+ run "[ ! -h #{runit_dir}/enabled/#{runit_delayed_job_service_name} ] || sv stop #{runit_dir}/enabled/#{runit_delayed_job_service_name}/ && rm -f #{runit_dir}/enabled/#{runit_delayed_job_service_name}"
28
+ end
29
+
30
+ desc "Restart delayed_job runit-service"
31
+ task :restart, :roles => :app do
32
+ run "[ ! -h #{runit_dir}/enabled/#{runit_delayed_job_service_name} ] || sv restart #{runit_dir}/enabled/#{runit_delayed_job_service_name}/"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,58 @@
1
+ Capistrano::Configuration.instance(true).load do
2
+ _cset :runit_unicorn_service_name, "unicorn"
3
+ _cset :runit_unicorn_template, File.expand_path(File.join(File.dirname(__FILE__), "../templates/run-unicorn.erb"))
4
+ _cset :runit_unicorn_command, "unicorn"
5
+ _cset :runit_unicorn_workers, 4
6
+ _cset :runit_unicorn_listen, "127.0.0.1"
7
+ _cset :runit_unicorn_port, 8080
8
+ _cset :runit_unicorn_after_fork_code, ""
9
+
10
+ namespace :runit do
11
+ namespace :unicorn do
12
+ desc "Setup Unicorn runit-service"
13
+ task :setup, :roles => :app do
14
+ run "[ -d #{runit_dir}/available/#{runit_unicorn_service_name} ] || mkdir -p #{runit_dir}/available/#{runit_unicorn_service_name}"
15
+ template = File.read(runit_unicorn_template)
16
+ erb_template = ERB.new(template)
17
+ servers = find_servers_for_task(current_task)
18
+ servers.each do |server|
19
+ runit_unicorn_listen_current =
20
+ if runit_unicorn_listen.is_a?(Hash)
21
+ runit_unicorn_listen[server.host]
22
+ else
23
+ runit_unicorn_listen
24
+ end
25
+ runit_unicorn_port_current =
26
+ if runit_unicorn_port.is_a?(Hash)
27
+ runit_unicorn_port[server.host]
28
+ else
29
+ runit_unicorn_port
30
+ end
31
+ runit_unicorn_workers_current =
32
+ if runit_unicorn_workers.is_a?(Hash)
33
+ runit_unicorn_workers[server.host]
34
+ else
35
+ runit_unicorn_workers
36
+ end
37
+ put erb_template.result(binding), "#{runit_dir}/available/#{runit_unicorn_service_name}/run", :mode => 0755, :hosts => server.host
38
+ end
39
+ find_and_execute_task "runit:unicorn:enable"
40
+ end
41
+
42
+ desc "Enable Unicorn runit-service"
43
+ task :enable, :roles => :app do
44
+ run "cd #{runit_dir}/enabled && [ -h ./#{runit_unicorn_service_name} ] || ln -sf ../available/#{runit_unicorn_service_name} ."
45
+ end
46
+
47
+ desc "Enable Unicorn runit-service"
48
+ task :disable, :roles => :app do
49
+ run "[ ! -h #{runit_dir}/enabled/#{runit_unicorn_service_name} ] || sv stop #{runit_dir}/enabled/#{runit_unicorn_service_name}/ && rm -f #{runit_dir}/enabled/#{runit_unicorn_service_name}"
50
+ end
51
+
52
+ desc "Restart Unicorn runit-service"
53
+ task :restart, :roles => :app do
54
+ run "[ ! -h #{runit_dir}/enabled/#{runit_unicorn_service_name} ] || sv restart #{runit_dir}/enabled/#{runit_unicorn_service_name}/"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ require "capistrano-runit/recipes/base"
2
+ require "capistrano-runit/recipes/unicorn"
3
+ require "capistrano-runit/recipes/delayed_job"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ cd <%= current_path %>
3
+ <%= runit_delayed_job_command %> run
@@ -0,0 +1,157 @@
1
+ #!/bin/bash -e
2
+
3
+ #
4
+ # Supervises unicorn; stopping this service prompts a graceful shutdown of the
5
+ # current unicorn instance. Sending HUP to this service causes unicorn to re-exec
6
+ # itself for upgrades etc.
7
+ #
8
+
9
+ ADDR=<%= runit_unicorn_listen_current %>
10
+ PORT=<%= runit_unicorn_port_current %>
11
+ APP_DIR="<%= current_path %>"
12
+ THIS_DIR=$(pwd)
13
+ CUR_PID_FILE=$APP_DIR/tmp/pids/unicorn.pid
14
+ OLD_PID_FILE=$CUR_PID_FILE.oldbin
15
+
16
+
17
+ if [ ! -d "$APP_DIR" ]; then
18
+ echo "no such app dir: $APP_DIR" 1>&2;
19
+ exit 2
20
+ fi
21
+
22
+ cat <<EOF > unicorn.rb
23
+ working_directory "$APP_DIR"
24
+ pid "$CUR_PID_FILE"
25
+
26
+ worker_processes <%= runit_unicorn_workers_current %>
27
+
28
+ preload_app true
29
+
30
+ # Restart any workers that haven't responded in 30 seconds
31
+ timeout 60
32
+
33
+ # listen on both a Unix domain socket and a TCP port,
34
+ #listen '$THIS_DIR/socket', :backlog => 64
35
+ listen '$ADDR:$PORT', :tcp_nopush => true
36
+
37
+ stderr_path "log/unicorn.stderr.log"
38
+ stdout_path "log/unicorn.stdout.log"
39
+
40
+ # http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
41
+ if GC.respond_to?(:copy_on_write_friendly=)
42
+ GC.copy_on_write_friendly = true
43
+ end
44
+
45
+
46
+ before_fork do |server, worker|
47
+ # the following is highly recomended for Rails + "preload_app true"
48
+ # as there's no need for the master process to hold a connection
49
+ if defined?(::ActiveRecord::Base)
50
+ ::ActiveRecord::Base.connection.disconnect!
51
+ end
52
+
53
+ ##
54
+ # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
55
+ # immediately start loading up a new version of itself (loaded with a new
56
+ # version of our app). When this new Unicorn is completely loaded
57
+ # it will begin spawning workers. The first worker spawned will check to
58
+ # see if an .oldbin pidfile exists. If so, this means we've just booted up
59
+ # a new Unicorn and need to tell the old one that it can now die. To do so
60
+ # we send it a QUIT.
61
+ #
62
+ # Using this method we get 0 downtime deploys.
63
+
64
+ old_pid = "$APP_DIR/tmp/pids/unicorn.pid.oldbin"
65
+ if File.exists?(old_pid) && server.pid != old_pid
66
+ begin
67
+ puts "Shutting down old process"
68
+ Process.kill("QUIT", File.read(old_pid).to_i)
69
+ rescue Errno::ENOENT, Errno::ESRCH
70
+ # someone else did our job for us
71
+ end
72
+ end
73
+ end
74
+
75
+
76
+ after_fork do |server, worker|
77
+ ##
78
+ # Unicorn master loads the app then forks off workers - because of the way
79
+ # Unix forking works, we need to make sure we aren't using any of the parent's
80
+ # sockets, e.g. db connection
81
+
82
+ if defined?(::ActiveRecord::Base)
83
+ ::ActiveRecord::Base.establish_connection
84
+ end
85
+
86
+ # Redis and Memcached would go here but their connections are established
87
+ # on demand, so the master never opens a socket
88
+ <% unless fetch(:runit_unicorn_after_fork_code, nil).nil? %>
89
+ <%= runit_unicorn_after_fork_code %>
90
+ <% end %>
91
+ end
92
+ EOF
93
+
94
+ function is_pid_running() {
95
+ set +e
96
+ if [ -n $1 ] && kill -0 $1 >/dev/null 2>&1; then
97
+ echo "yes"
98
+ fi
99
+ set -e
100
+ }
101
+
102
+ echo "My pid: $$"
103
+
104
+ if [ -e $OLD_PID_FILE ]; then
105
+ OLD_PID=$(cat $OLD_PID_FILE)
106
+ echo "Unicorn appears to be restarting: waiting for old master ($OLD_PID) to exit"
107
+ while [ -n "$(is_pid_running $OLD_PID)" ]; do
108
+ /bin/echo -n '.'
109
+ sleep 2
110
+ done
111
+ fi
112
+
113
+ if [ -e $CUR_PID_FILE ]; then
114
+ CUR_PID=$(cat $CUR_PID_FILE)
115
+ if [ -n "$(is_pid_running $CUR_PID)" ]; then
116
+ echo "Already running as $CUR_PID"
117
+ RUNNING=true
118
+ fi
119
+ fi
120
+
121
+ if [ ! $RUNNING ]; then
122
+ echo "Starting unicorn"
123
+ old=$(pwd)
124
+ cd $APP_DIR
125
+ <%= runit_unicorn_command %> -E production -c $THIS_DIR/unicorn.rb -D
126
+ cd $old
127
+ sleep 2
128
+ CUR_PID=$(cat $CUR_PID_FILE)
129
+ fi
130
+
131
+ function restart() {
132
+ # TODO: regenerate config if this file has changed
133
+
134
+ # Tell unicorn to re-exec itself
135
+ echo "Asking unicorn to re-exec itself with USR2"
136
+ kill -USR2 $CUR_PID
137
+ # Wait and then exit -- after runit restarts the script, we'll
138
+ # wait for the re-exec'd process
139
+ sleep 2
140
+ echo "Restarting to supervise new unicorn"
141
+ exit
142
+ }
143
+
144
+ function graceful_shutdown() {
145
+ echo "Requesting graceful shutdown"
146
+ kill -QUIT $CUR_PID
147
+ }
148
+
149
+ trap restart HUP QUIT
150
+ trap graceful_shutdown INT TERM
151
+
152
+ echo "Watching for unicorn ($CUR_PID) exiting"
153
+ while [ -n "$(is_pid_running $CUR_PID)" ]; do
154
+ /bin/echo -n '.'
155
+ sleep 2
156
+ done
157
+ echo "Unicorn has exited."
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-runit
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Anton Ageev
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-15 00:00:00 +04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: capistrano
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ version: 2.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description:
38
+ email: antage@gmail.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - .gitignore
47
+ - Gemfile
48
+ - README.markdown
49
+ - capistrano-runit.gemspec
50
+ - lib/capistrano-runit/recipes.rb
51
+ - lib/capistrano-runit/recipes/base.rb
52
+ - lib/capistrano-runit/recipes/delayed_job.rb
53
+ - lib/capistrano-runit/recipes/unicorn.rb
54
+ - lib/capistrano-runit/templates/run-delayed_job.erb
55
+ - lib/capistrano-runit/templates/run-unicorn.erb
56
+ has_rdoc: true
57
+ homepage: http://github.com/antage/capistrano-runit
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options: []
62
+
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.6.2
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Useful deployment recipes.
90
+ test_files: []
91
+