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 +1 -1
- data/LICENSE +7 -0
- data/README.md +47 -18
- data/capistrano-unicorn.gemspec +2 -0
- data/lib/capistrano-unicorn/capistrano_integration.rb +188 -66
- data/lib/capistrano-unicorn/version.rb +1 -1
- metadata +28 -5
data/Gemfile
CHANGED
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
|
-
|
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
|
-
|
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
|
-
|
31
|
+
Add unicorn restart task hook:
|
30
32
|
|
31
|
-
|
33
|
+
```ruby
|
34
|
+
after 'deploy:restart', 'unicorn:reload' # app IS NOT preloaded
|
35
|
+
after 'deploy:restart', 'unicorn:restart' # app preloaded
|
36
|
+
```
|
32
37
|
|
33
|
-
|
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
|
-
|
58
|
+
## Configuration
|
42
59
|
|
43
|
-
|
60
|
+
You can modify any of the following options in your `deploy.rb` config.
|
44
61
|
|
45
|
-
-
|
46
|
-
-
|
47
|
-
-
|
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
|
-
|
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
|
-
|
70
|
+
## Available Tasks
|
52
71
|
|
53
|
-
|
72
|
+
To get a list of all capistrano tasks, run `cap -T`:
|
54
73
|
|
55
|
-
|
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
|
-
|
86
|
+
See LICENSE file for details.
|
data/capistrano-unicorn.gemspec
CHANGED
@@ -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
|
29
|
+
# Check if a remote process exists using its pid file
|
10
30
|
#
|
11
|
-
def
|
12
|
-
|
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
|
-
#
|
34
|
+
|
35
|
+
# Stale Unicorn process pid file
|
16
36
|
#
|
17
|
-
def
|
18
|
-
|
37
|
+
def old_unicorn_pid
|
38
|
+
"#{unicorn_pid}.oldbin"
|
19
39
|
end
|
20
40
|
|
21
|
-
#
|
41
|
+
# Command to check if Unicorn is running
|
22
42
|
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
_cset(:unicorn_bin, "unicorn")
|
43
|
+
def unicorn_is_running?
|
44
|
+
remote_process_exists?(unicorn_pid)
|
45
|
+
end
|
27
46
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
if
|
42
|
-
|
43
|
-
|
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
|
-
|
46
|
-
|
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
|
-
|
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 '
|
65
|
-
task :
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
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
|
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.
|
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:
|
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:
|
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:
|
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.
|
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:
|