capistrano-unicorn 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source 'http://rubygems.org'
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2011-2012 Dan Sosedoff.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -4,33 +4,50 @@ Capistrano plugin that integrates Unicorn tasks into capistrano deployment scrip
4
4
 
5
5
  ## Installation
6
6
 
7
+ Install library from rubygems:
8
+
7
9
  ```
8
10
  gem install capistrano-unicorn
9
11
  ```
10
12
 
11
13
  ## Usage
12
14
 
13
- Add the gem to your ```Gemfile```:
15
+ ### Setup
16
+
17
+ Add the library to your `Gemfile`:
14
18
 
15
19
  ```ruby
16
20
  group :development do
17
- gem 'capistrano-unicorn'
21
+ gem 'capistrano-unicorn', :require => false
18
22
  end
19
23
  ```
20
24
 
21
- Add unicorn plugin into your deploy.rb file.
22
-
23
- **NOTE:** Should be placed after all hooks
25
+ And load it into your deployment script `config/deploy.rb`:
24
26
 
25
27
  ```ruby
26
28
  require 'capistrano-unicorn'
27
29
  ```
28
30
 
29
- This should add a unicorn server start task after ```deploy:restart```.
31
+ Add unicorn restart task hook:
30
32
 
31
- Unicorn configuration file should be placed under ```config/unicorn/YOUR_ENV.rb```
33
+ ```ruby
34
+ after 'deploy:restart', 'unicorn:reload' # app IS NOT preloaded
35
+ after 'deploy:restart', 'unicorn:restart' # app preloaded
36
+ ```
32
37
 
33
- To test if it works type:
38
+ Create a new configuration file `config/unicorn/unicorn.rb` or `config/unicorn/STAGE.rb`, where stage is your deployment environment.
39
+
40
+ Example config - [examples/rails3.rb](https://github.com/sosedoff/capistrano-unicorn/blob/master/examples/rails3.rb). Please refer to unicorn documentation for more examples and configuration options.
41
+
42
+ ### Test
43
+
44
+ First, make sure you're running the latest release:
45
+
46
+ ```
47
+ cap deploy
48
+ ```
49
+
50
+ Then you can test each individual task:
34
51
 
35
52
  ```
36
53
  cap unicorn:start
@@ -38,20 +55,32 @@ cap unicorn:stop
38
55
  cap unicorn:reload
39
56
  ```
40
57
 
41
- **NOTE:** This plugin uses bundler.
58
+ ## Configuration
42
59
 
43
- ## Configuration options
60
+ You can modify any of the following options in your `deploy.rb` config.
44
61
 
45
- - ```unicorn_env``` - Set unicorn environment. Default to ```rails_env``` variable.
46
- - ```unicorn_pid``` - Set unicorn PID file path. Default to ```current_path/tmp/pids/unicorn.pid```
47
- - ```unicorn_bin``` - Set unicorn executable file. Default to ```unicorn```.
62
+ - `unicorn_env` - Set unicorn environment. Default to `rails_env` variable.
63
+ - `unicorn_pid` - Set unicorn PID file path. Default to `current_path/tmp/pids/unicorn.pid`
64
+ - `unicorn_bin` - Set unicorn executable file. Default to `unicorn`.
65
+ - `unicorn_bundle` - Set bundler command for unicorn. Default to `bundle`.
66
+ - `unicorn_user` - Launch unicorn master as the specified user. Default to `user` variable.
48
67
 
49
- ## License
68
+ If you are using capistrano multistage, please refer to [Using capistrano unicorn with multistage environment](https://github.com/sosedoff/capistrano-unicorn/wiki/Using-capistrano-unicorn-with-multistage-environment).
50
69
 
51
- Copyright (c) 2011-2012 Dan Sosedoff.
70
+ ## Available Tasks
52
71
 
53
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
72
+ To get a list of all capistrano tasks, run `cap -T`:
54
73
 
55
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
74
+ ```
75
+ cap unicorn:add_worker # Add a new worker
76
+ cap unicorn:remove_worker # Remove amount of workers
77
+ cap unicorn:reload # Reload Unicorn
78
+ cap unicorn:restart # Restart Unicorn
79
+ cap unicorn:shutdown # Immediately shutdown Unicorn
80
+ cap unicorn:start # Start Unicorn master process
81
+ cap unicorn:stop # Stop Unicorn
82
+ ```
83
+
84
+ ## License
56
85
 
57
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
86
+ See LICENSE file for details.
@@ -14,6 +14,8 @@ Gem::Specification.new do |gem|
14
14
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
15
  gem.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
16
16
  gem.require_paths = ['lib']
17
+
18
+ gem.add_development_dependency 'rake'
17
19
 
18
20
  gem.add_runtime_dependency 'capistrano'
19
21
  end
@@ -3,97 +3,219 @@ require 'capistrano/version'
3
3
 
4
4
  module CapistranoUnicorn
5
5
  class CapistranoIntegration
6
+ TASKS = [
7
+ 'unicorn:start',
8
+ 'unicorn:stop',
9
+ 'unicorn:restart',
10
+ 'unicorn:duplicate',
11
+ 'unicorn:reload',
12
+ 'unicorn:shutdown',
13
+ 'unicorn:add_worker',
14
+ 'unicorn:remove_worker'
15
+ ]
16
+
6
17
  def self.load_into(capistrano_config)
7
18
  capistrano_config.load do
19
+ before(CapistranoIntegration::TASKS) do
20
+ _cset(:app_env) { (fetch(:rails_env) rescue 'production') }
21
+ _cset(:unicorn_pid) { "#{fetch(:current_path)}/tmp/pids/unicorn.pid" }
22
+ _cset(:unicorn_env) { fetch(:app_env) }
23
+ _cset(:unicorn_bin) { "unicorn" }
24
+ _cset(:unicorn_bundle) { fetch(:bundle_cmd) rescue 'bundle' }
25
+ _cset(:unicorn_restart_sleep_time) { 2 }
26
+ _cset(:unicorn_user) { nil }
27
+ end
8
28
 
9
- # Check if remote file exists
29
+ # Check if a remote process exists using its pid file
10
30
  #
11
- def remote_file_exists?(full_path)
12
- 'true' == capture("if [ -e #{full_path} ]; then echo 'true'; fi").strip
31
+ def remote_process_exists?(pid_file)
32
+ "[ -e #{pid_file} ] && #{try_unicorn_user} kill -0 `cat #{pid_file}` > /dev/null 2>&1"
13
33
  end
14
-
15
- # Check if process is running
34
+
35
+ # Stale Unicorn process pid file
16
36
  #
17
- def process_exists?(pid_file)
18
- capture("ps -p $(cat #{pid_file}) ; true").strip.split("\n").size == 2
37
+ def old_unicorn_pid
38
+ "#{unicorn_pid}.oldbin"
19
39
  end
20
40
 
21
- # Set unicorn vars
41
+ # Command to check if Unicorn is running
22
42
  #
23
- _cset(:unicorn_pid, "#{fetch(:current_path)}/tmp/pids/unicorn.pid")
24
- _cset(:app_env, (fetch(:rails_env) rescue 'production'))
25
- _cset(:unicorn_env, (fetch(:app_env)))
26
- _cset(:unicorn_bin, "unicorn")
43
+ def unicorn_is_running?
44
+ remote_process_exists?(unicorn_pid)
45
+ end
27
46
 
28
- namespace :unicorn do
29
- desc 'Start Unicorn'
30
- task :start, :roles => :app, :except => {:no_release => true} do
31
- if remote_file_exists?(unicorn_pid)
32
- if process_exists?(unicorn_pid)
33
- logger.important("Unicorn is already running!", "Unicorn")
34
- next
47
+ # Command to check if stale Unicorn is running
48
+ #
49
+ def old_unicorn_is_running?
50
+ remote_process_exists?(old_unicorn_pid)
51
+ end
52
+
53
+ # Get unicorn master process PID (using the shell)
54
+ #
55
+ def get_unicorn_pid(pid_file=unicorn_pid)
56
+ "`cat #{pid_file}`"
57
+ end
58
+
59
+ # Get unicorn master (old) process PID
60
+ #
61
+ def get_old_unicorn_pid
62
+ get_unicorn_pid(old_unicorn_pid)
63
+ end
64
+
65
+ # Send a signal to a unicorn master processes
66
+ #
67
+ def unicorn_send_signal(signal, pid=get_unicorn_pid)
68
+ "#{try_unicorn_user} kill -s #{signal} #{pid}"
69
+ end
70
+
71
+ # Run a command as the :unicorn_user user if :unicorn_user is a string.
72
+ # Otherwise run as default (:user) user.
73
+ #
74
+ def try_unicorn_user
75
+ "#{sudo :as => unicorn_user.to_s}" if unicorn_user.kind_of?(String)
76
+ end
77
+
78
+ # Kill Unicorns in multiple ways O_O
79
+ #
80
+ def kill_unicorn(signal)
81
+ script = <<-END
82
+ set -x;
83
+ if #{unicorn_is_running?}; then
84
+ echo "Stopping Unicorn...";
85
+ #{unicorn_send_signal(signal)};
86
+ else
87
+ echo "Unicorn is not running.";
88
+ fi;
89
+ END
90
+
91
+ script
92
+ end
93
+
94
+ # Start the Unicorn server
95
+ #
96
+ def start_unicorn
97
+ primary_config_path = "#{current_path}/config/unicorn.rb"
98
+ secondary_config_path = "#{current_path}/config/unicorn/#{unicorn_env}.rb"
99
+
100
+ script = <<-END
101
+ set -x;
102
+ if [ -e #{primary_config_path} ]; then
103
+ UNICORN_CONFIG_PATH=#{primary_config_path};
104
+ else
105
+ if [ -e #{secondary_config_path} ]; then
106
+ UNICORN_CONFIG_PATH=#{secondary_config_path};
35
107
  else
36
- run "rm #{unicorn_pid}"
37
- end
38
- end
39
-
40
- config_path = "#{current_path}/config/unicorn/#{unicorn_env}.rb"
41
- if remote_file_exists?(config_path)
42
- logger.important("Starting...", "Unicorn")
43
- run "cd #{current_path} && BUNDLE_GEMFILE=#{current_path}/Gemfile bundle exec #{unicorn_bin} -c #{config_path} -E #{app_env} -D"
108
+ echo "Config file for \"#{unicorn_env}\" environment was not found at either \"#{primary_config_path}\" or \"#{secondary_config_path}\"";
109
+ exit 1;
110
+ fi;
111
+ fi;
112
+
113
+ if [ -e #{unicorn_pid} ]; then
114
+ if #{try_unicorn_user} kill -0 `cat #{unicorn_pid}` > /dev/null 2>&1; then
115
+ echo "Unicorn is already running!";
116
+ exit 0;
117
+ fi;
118
+
119
+ #{try_unicorn_user} rm #{unicorn_pid};
120
+ fi;
121
+
122
+ echo "Starting Unicorn...";
123
+ cd #{current_path} && #{try_unicorn_user} BUNDLE_GEMFILE=#{current_path}/Gemfile #{unicorn_bundle} exec #{unicorn_bin} -c $UNICORN_CONFIG_PATH -E #{app_env} -D;
124
+ END
125
+
126
+ script
127
+ end
128
+
129
+ def duplicate_unicorn
130
+ script = <<-END
131
+ set -x;
132
+ if #{unicorn_is_running?}; then
133
+ echo "Duplicating Unicorn...";
134
+ #{unicorn_send_signal('USR2')};
44
135
  else
45
- logger.important("Config file for \"#{unicorn_env}\" environment was not found at \"#{config_path}\"", "Unicorn")
46
- end
136
+ #{start_unicorn}
137
+ fi;
138
+ END
139
+
140
+ script
141
+ end
142
+
143
+ #
144
+ # Unicorn cap tasks
145
+ #
146
+ namespace :unicorn do
147
+ desc 'Start Unicorn master process'
148
+ task :start, :roles => :app, :except => {:no_release => true} do
149
+ run start_unicorn
47
150
  end
48
151
 
49
152
  desc 'Stop Unicorn'
50
153
  task :stop, :roles => :app, :except => {:no_release => true} do
51
- if remote_file_exists?(unicorn_pid)
52
- if process_exists?(unicorn_pid)
53
- logger.important("Stopping...", "Unicorn")
54
- run "#{try_sudo} kill `cat #{unicorn_pid}`"
55
- else
56
- run "rm #{unicorn_pid}"
57
- logger.important("Unicorn is not running.", "Unicorn")
58
- end
59
- else
60
- logger.important("No PIDs found. Check if unicorn is running.", "Unicorn")
61
- end
154
+ run kill_unicorn('QUIT')
62
155
  end
63
156
 
64
- desc 'Unicorn graceful shutdown'
65
- task :graceful_stop, :roles => :app, :except => {:no_release => true} do
66
- if remote_file_exists?(unicorn_pid)
67
- if process_exists?(unicorn_pid)
68
- logger.important("Stopping...", "Unicorn")
69
- run "#{try_sudo} kill -s QUIT `cat #{unicorn_pid}`"
70
- else
71
- run "rm #{unicorn_pid}"
72
- logger.important("Unicorn is not running.", "Unicorn")
73
- end
74
- else
75
- logger.important("No PIDs found. Check if unicorn is running.", "Unicorn")
76
- end
157
+ desc 'Immediately shutdown Unicorn'
158
+ task :shutdown, :roles => :app, :except => {:no_release => true} do
159
+ run kill_unicorn('TERM')
160
+ end
161
+
162
+ desc 'Restart Unicorn'
163
+ task :restart, :roles => :app, :except => {:no_release => true} do
164
+ run <<-END
165
+ #{duplicate_unicorn}
166
+
167
+ sleep #{unicorn_restart_sleep_time}; # in order to wait for the (old) pidfile to show up
168
+
169
+ if #{old_unicorn_is_running?}; then
170
+ #{unicorn_send_signal('QUIT', get_old_unicorn_pid)};
171
+ fi;
172
+ END
173
+ end
174
+
175
+ desc 'Duplicate Unicorn'
176
+ task :duplicate, :roles => :app, :except => {:no_release => true} do
177
+ run duplicate_unicorn()
77
178
  end
78
179
 
79
180
  desc 'Reload Unicorn'
80
181
  task :reload, :roles => :app, :except => {:no_release => true} do
81
- if remote_file_exists?(unicorn_pid)
82
- logger.important("Stopping...", "Unicorn")
83
- run "#{try_sudo} kill -s USR2 `cat #{unicorn_pid}`"
84
- else
85
- logger.important("No PIDs found. Starting Unicorn server...", "Unicorn")
86
- config_path = "#{current_path}/config/unicorn/#{unicorn_env}.rb"
87
- if remote_file_exists?(config_path)
88
- run "cd #{current_path} && BUNDLE_GEMFILE=#{current_path}/Gemfile bundle exec #{unicorn_bin} -c #{config_path} -E #{app_env} -D"
182
+ run <<-END
183
+ set -x;
184
+ if #{unicorn_is_running?}; then
185
+ echo "Reloading Unicorn...";
186
+ #{unicorn_send_signal('HUP')};
89
187
  else
90
- logger.important("Config file for \"#{unicorn_env}\" environment was not found at \"#{config_path}\"", "Unicorn")
91
- end
92
- end
188
+ #{start_unicorn}
189
+ fi;
190
+ END
191
+ end
192
+
193
+ desc 'Add a new worker'
194
+ task :add_worker, :roles => :app, :except => {:no_release => true} do
195
+ run <<-END
196
+ set -x;
197
+ if #{unicorn_is_running?}; then
198
+ echo "Adding a new Unicorn worker...";
199
+ #{unicorn_send_signal('TTIN')};
200
+ else
201
+ echo "Unicorn is not running.";
202
+ fi;
203
+ END
93
204
  end
94
- end
95
205
 
96
- after "deploy:restart", "unicorn:reload"
206
+ desc 'Remove amount of workers'
207
+ task :remove_worker, :roles => :app, :except => {:no_release => true} do
208
+ run <<-END
209
+ set -x;
210
+ if #{unicorn_is_running?}; then
211
+ echo "Removing a Unicorn worker...";
212
+ #{unicorn_send_signal('TTOU')};
213
+ else
214
+ echo "Unicorn is not running.";
215
+ fi;
216
+ END
217
+ end
218
+ end
97
219
  end
98
220
  end
99
221
  end
@@ -1,5 +1,5 @@
1
1
  module CapistranoUnicorn
2
2
  unless defined?(::CapistranoUnicorn::VERSION)
3
- VERSION = "0.1.6".freeze
3
+ VERSION = "0.1.7".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-unicorn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-23 00:00:00.000000000Z
12
+ date: 2013-03-21 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: capistrano
16
- requirement: &2166810460 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
17
33
  none: false
18
34
  requirements:
19
35
  - - ! '>='
@@ -21,7 +37,12 @@ dependencies:
21
37
  version: '0'
22
38
  type: :runtime
23
39
  prerelease: false
24
- version_requirements: *2166810460
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
25
46
  description: Capistrano plugin that integrates Unicorn server tasks.
26
47
  email: dan.sosedoff@gmail.com
27
48
  executables: []
@@ -30,6 +51,7 @@ extra_rdoc_files: []
30
51
  files:
31
52
  - .gitignore
32
53
  - Gemfile
54
+ - LICENSE
33
55
  - README.md
34
56
  - Rakefile
35
57
  - capistrano-unicorn.gemspec
@@ -57,8 +79,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
79
  version: '0'
58
80
  requirements: []
59
81
  rubyforge_project:
60
- rubygems_version: 1.8.15
82
+ rubygems_version: 1.8.24
61
83
  signing_key:
62
84
  specification_version: 3
63
85
  summary: Unicorn integration for Capistrano
64
86
  test_files: []
87
+ has_rdoc: