capistrano-unicorn-edge 0.1.4
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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/Rakefile +2 -0
- data/capistrano-unicorn.gemspec +24 -0
- data/examples/unicorn.rb +52 -0
- data/lib/capistrano/tasks/unicorn.cap +124 -0
- data/lib/capistrano/unicorn.rb +23 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ea77bba82cc4703c42b81691b9da9cde60ef05c3
|
4
|
+
data.tar.gz: dfe67836b374e0b635bec316a494363d4c8593b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 87461ffd0a9804cc42da3c3b7b8272ab280612ab6643489f64f34b7d9ce98882823ae7641488e015f8b243283df2c5920b19a288431c55f7a34855774d2da5ee
|
7
|
+
data.tar.gz: 3f132926442f85b297fd8df88fb4a172541350952305bd1729c576396a3b1203f9f94aa8259636d6c3e9b7dff1cb50c37a787bfa56076d4c892c918cb95267e2
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Alexander Menzhinsky
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Capistrano 3.x :: Unicorn
|
2
|
+
|
3
|
+
Unicorn specific tasks for Capistrano 3.x
|
4
|
+
|
5
|
+
```
|
6
|
+
cap unicorn:start # Start unicorn
|
7
|
+
cap unicorn:stop # Stop unicorn gracefully (QUIT)
|
8
|
+
cap unicorn:shutdown # Stop unicorn immediately (TERM)
|
9
|
+
cap unicorn:restart # Restart unicorn, invokes unicorn:restart_usr2
|
10
|
+
cap unicorn:restart_hup # Restart unicorn, when preload_app is false (HUP)
|
11
|
+
cap unicorn:restart_usr2 # Restart unicorn, when before_fork hook is set and preload_app is true (USR2)
|
12
|
+
cap unicorn:restart_usr2_quit # Restart unicorn, when before_fork hook is not set and preload_app is true (USR2 + QUIT)
|
13
|
+
cap unicorn:add_worker[count] # Add a worker (TTIN)
|
14
|
+
cap unicorn:remove_worker[count] # Remove a worker (TTOU)
|
15
|
+
cap unicorn:stop_workers # Stop all workers but keep the master running (WINCH)
|
16
|
+
cap unicorn:reopen_logs # Reopen all logs owned by the master and all workers (USR1)
|
17
|
+
```
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add this line to your application's Gemfile:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem 'capistrano-unicorn-edge', require: false, group: :development
|
25
|
+
```
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
```
|
29
|
+
$ bundle
|
30
|
+
```
|
31
|
+
|
32
|
+
Or install it yourself as:
|
33
|
+
```
|
34
|
+
$ gem install capistrano-unicorn-edge
|
35
|
+
```
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Require in `Capfile` to use tasks:
|
40
|
+
```ruby
|
41
|
+
require 'capistrano/unicorn'
|
42
|
+
```
|
43
|
+
|
44
|
+
Configurable options:
|
45
|
+
```ruby
|
46
|
+
set :unicorn_pid, -> { current_path.join('tmp/pids/unicorn.pid') } # this is default
|
47
|
+
set :unicorn_config, -> { current_path.join("config/unicorn/#{fetch(:rails_env)}.rb") } # this is default
|
48
|
+
set :unicorn_roles, :app # this is default
|
49
|
+
set :unicorn_options, '' # this is default
|
50
|
+
set :unicorn_restart_delay, 5 # this is default
|
51
|
+
set :unicorn_rack_env, :deployment # this is default
|
52
|
+
set :unicorn_restart_method, :restart_usr2 # this is default
|
53
|
+
```
|
54
|
+
|
55
|
+
Everything should work **out-of-box** but you need to **set up unicorn's config**. (see an example `examples/unicorn.rb`).
|
56
|
+
|
57
|
+
There are three different ways to restart server:
|
58
|
+
* `:restart_hup` reloads config file and gracefully restart all workers, if `preload_app` is true, then application code changes will have no effect
|
59
|
+
* `:restart_usr2_quit` re-execute the running binary and kill old instance in a time interval specified in `:unicorn_restart_delay`, but this method can't be absolutely reliable
|
60
|
+
* `:restart_usr2` the same as above but `before_fork` hook which kills old instance has to be set, default and the best choice
|
61
|
+
|
62
|
+
## Contributing
|
63
|
+
|
64
|
+
1. Fork it ( https://github.com/amenzhinsky/capistrano-unicorn-edge/fork )
|
65
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
66
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
67
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
68
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "capistrano-unicorn-edge"
|
7
|
+
spec.version = "0.1.4"
|
8
|
+
spec.authors = ["Alexander Menzhinsky"]
|
9
|
+
spec.email = ["amenzhinsky@gmail.com"]
|
10
|
+
spec.summary = %q{Unicorn support for Capistrano 3.x}
|
11
|
+
spec.description = %q{Unicorn support for Capistrano 3.x}
|
12
|
+
spec.homepage = "https://github.com/amenzhinsky/capistrano-unicorn-edge"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency 'capistrano', '~> 3.1'
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
end
|
data/examples/unicorn.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Set your full path to application.
|
2
|
+
app_path = '/home/deploy/web-app/current'
|
3
|
+
|
4
|
+
# Set unicorn options
|
5
|
+
worker_processes 2
|
6
|
+
preload_app true
|
7
|
+
check_client_connection false
|
8
|
+
timeout 30
|
9
|
+
|
10
|
+
listen "#{app_path}/tmp/sockets/unicorn.sock", backlog: 64
|
11
|
+
listen 8888, tcp_nopush: true
|
12
|
+
|
13
|
+
# Spawn unicorn master worker for user deploy (group: deploy)
|
14
|
+
user 'deploy', 'deploy'
|
15
|
+
|
16
|
+
# Fill path to your app
|
17
|
+
working_directory app_path
|
18
|
+
|
19
|
+
# Log everything to one file
|
20
|
+
stderr_path "#{app_path}/log/unicorn.log"
|
21
|
+
stdout_path "#{app_path}/log/unicorn.log"
|
22
|
+
|
23
|
+
# Set master PID location
|
24
|
+
pid "#{app_path}/tmp/pids/unicorn.pid"
|
25
|
+
|
26
|
+
before_fork do |server, worker|
|
27
|
+
##
|
28
|
+
# When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
|
29
|
+
# immediately start loading up a new version of itself (loaded with a new
|
30
|
+
# version of our app). When this new Unicorn is completely loaded
|
31
|
+
# it will begin spawning workers. The first worker spawned will check to
|
32
|
+
# see if an .oldbin pidfile exists. If so, this means we've just booted up
|
33
|
+
# a new Unicorn and need to tell the old one that it can now die. To do so
|
34
|
+
# we send it a QUIT.
|
35
|
+
#
|
36
|
+
# Using this method we get 0 downtime deploys.
|
37
|
+
ActiveRecord::Base.connection.disconnect!
|
38
|
+
|
39
|
+
old_pid = "#{server.config[:pid]}.oldbin"
|
40
|
+
|
41
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
42
|
+
begin
|
43
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
44
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
45
|
+
# someone else did our job for us
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
after_fork do |server, worker|
|
51
|
+
ActiveRecord::Base.establish_connection
|
52
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
namespace :unicorn do
|
2
|
+
desc 'Start unicorn'
|
3
|
+
task :start do
|
4
|
+
on roles(fetch(:unicorn_roles)) do
|
5
|
+
unicorn_start unless unicorn_is_running?
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
desc 'Stop unicorn gracefully (QUIT)'
|
10
|
+
task :stop do
|
11
|
+
on roles(fetch(:unicorn_roles)) do
|
12
|
+
unicorn_send_signal(:QUIT) if unicorn_is_running?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Stop unicorn immediately (TERM)'
|
17
|
+
task :shutdown do
|
18
|
+
on roles(fetch(:unicorn_roles)) do
|
19
|
+
unicorn_send_signal('TERM') if unicorn_is_running?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Restart unicorn'
|
24
|
+
task :restart do
|
25
|
+
invoke "unicorn:#{fetch(:unicorn_restart_method)}"
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'Restart unicorn, when preload_app is false (HUP)'
|
29
|
+
task :restart_hup do
|
30
|
+
on roles(fetch(:unicorn_roles)) do
|
31
|
+
if unicorn_is_running?
|
32
|
+
unicorn_send_signal(:HUP)
|
33
|
+
else
|
34
|
+
unicorn_start
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'Restart unicorn, when before_fork hook is set and preload_app is true (USR2)'
|
40
|
+
task :restart_usr2 do
|
41
|
+
on roles(fetch(:unicorn_roles)) do
|
42
|
+
if unicorn_is_running?
|
43
|
+
unicorn_send_signal(:USR2)
|
44
|
+
else
|
45
|
+
unicorn_start
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'Restart unicorn, when before_fork hook is not set and preload_app is true (USR2 + QUIT)'
|
51
|
+
task :restart_usr2_quit do
|
52
|
+
on roles(fetch(:unicorn_roles)) do
|
53
|
+
if unicorn_is_running?
|
54
|
+
unicorn_send_signal(:USR2)
|
55
|
+
|
56
|
+
execute :sleep, fetch(:unicorn_restart_delay)
|
57
|
+
|
58
|
+
if unicorn_is_running?(unicorn_old_pid)
|
59
|
+
unicorn_send_signal(:QUIT, unicorn_old_pid)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
unicorn_start
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'Add a worker (TTIN)'
|
68
|
+
task :add_worker, :count do |_, args|
|
69
|
+
on roles(fetch(:unicorn_roles)) do
|
70
|
+
if unicorn_is_running?
|
71
|
+
args.fetch(:count, 1).to_i.times do
|
72
|
+
unicorn_send_signal(:TTIN)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
error 'unicorn is not running'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
desc 'Remove a worker (TTOU)'
|
81
|
+
task :remove_worker, :count do |_, args|
|
82
|
+
on roles(fetch(:unicorn_roles)) do
|
83
|
+
if unicorn_is_running?
|
84
|
+
args.fetch(:count, 1).to_i.times do
|
85
|
+
unicorn_send_signal(:TTOU)
|
86
|
+
end
|
87
|
+
else
|
88
|
+
error 'unicorn is not running'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'Stop all workers but keep the master running (WINCH)'
|
94
|
+
task :stop_workers do
|
95
|
+
if unicorn_is_running?
|
96
|
+
unicorn_send_signal(:WINCH)
|
97
|
+
else
|
98
|
+
error 'unicorn is not running'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
desc 'Reopen all logs owned by the master and all workers (USR1)'
|
103
|
+
task :reopen_logs do
|
104
|
+
if unicorn_is_running?
|
105
|
+
unicorn_send_signal(:USR1)
|
106
|
+
else
|
107
|
+
error 'unicorn is not running'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
namespace :load do
|
113
|
+
task :defaults do
|
114
|
+
set :unicorn_pid, -> { current_path.join('tmp/pids/unicorn.pid') }
|
115
|
+
set :unicorn_config, -> { current_path.join("config/unicorn/#{fetch(:rails_env)}.rb") }
|
116
|
+
set :unicorn_roles, :app
|
117
|
+
set :unicorn_options, ''
|
118
|
+
set :unicorn_restart_delay, 5
|
119
|
+
set :unicorn_rack_env, :deployment
|
120
|
+
set :unicorn_restart_method, :restart_usr2
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
after 'deploy:published', 'unicorn:restart'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
def unicorn_is_running?(pidfile = fetch(:unicorn_pid))
|
2
|
+
test "[[ -e #{pidfile} ]] && $(kill -0 $(cat #{pidfile}) &> /dev/null)"
|
3
|
+
end
|
4
|
+
|
5
|
+
def unicorn_start
|
6
|
+
within release_path do
|
7
|
+
with rails_env: fetch(:rails_env) do
|
8
|
+
execute :bundle, 'exec', 'unicorn', '-c', fetch(:unicorn_config),
|
9
|
+
'-E', fetch(:unicorn_rack_env),
|
10
|
+
'-D', fetch(:unicorn_options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def unicorn_old_pid
|
16
|
+
"#{fetch(:unicorn_pid)}.oldbin"
|
17
|
+
end
|
18
|
+
|
19
|
+
def unicorn_send_signal(signal, pidfile = fetch(:unicorn_pid))
|
20
|
+
execute :kill, "-#{signal}", capture(:cat, pidfile)
|
21
|
+
end
|
22
|
+
|
23
|
+
load File.expand_path('../tasks/unicorn.cap', __FILE__)
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capistrano-unicorn-edge
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Menzhinsky
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: capistrano
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Unicorn support for Capistrano 3.x
|
56
|
+
email:
|
57
|
+
- amenzhinsky@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- capistrano-unicorn.gemspec
|
68
|
+
- examples/unicorn.rb
|
69
|
+
- lib/capistrano/tasks/unicorn.cap
|
70
|
+
- lib/capistrano/unicorn.rb
|
71
|
+
homepage: https://github.com/amenzhinsky/capistrano-unicorn-edge
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.2.2
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Unicorn support for Capistrano 3.x
|
95
|
+
test_files: []
|