sepastian-capistrano3-unicorn 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +41 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +9 -0
- data/LICENSE +18 -0
- data/NEWS.md +27 -0
- data/README.md +177 -0
- data/Rakefile +10 -0
- data/capistrano-unicorn.gemspec +22 -0
- data/examples/rails3.rb +45 -0
- data/lib/capistrano-unicorn.rb +0 -0
- data/lib/capistrano/tasks/unicorn.cap +170 -0
- data/lib/capistrano/unicorn.rb +1 -0
- data/lib/capistrano/unicorn/utility.rb +166 -0
- data/lib/capistrano/unicorn/version.rb +5 -0
- data/lib/unicorn.rb +0 -0
- data/spec/capistrano_integration_spec.rb +84 -0
- data/spec/config_spec.rb +134 -0
- data/spec/spec_helper.rb +7 -0
- metadata +113 -0
data/.gitignore
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
!.gitignore
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
*.sw[a-p]
|
5
|
+
*.tmproj
|
6
|
+
*.tmproject
|
7
|
+
*.un~
|
8
|
+
*~
|
9
|
+
.DS_Store
|
10
|
+
.Spotlight-V100
|
11
|
+
.Trashes
|
12
|
+
._*
|
13
|
+
.bundle
|
14
|
+
.config
|
15
|
+
.directory
|
16
|
+
.elc
|
17
|
+
.redcar
|
18
|
+
.yardoc
|
19
|
+
/.emacs.desktop
|
20
|
+
/.emacs.desktop.lock
|
21
|
+
Desktop.ini
|
22
|
+
Gemfile.lock
|
23
|
+
Icon?
|
24
|
+
InstalledFiles
|
25
|
+
Session.vim
|
26
|
+
Thumbs.db
|
27
|
+
\#*\#
|
28
|
+
_yardoc
|
29
|
+
auto-save-list
|
30
|
+
coverage
|
31
|
+
doc/
|
32
|
+
lib/bundler/man
|
33
|
+
pkg
|
34
|
+
pkg/*
|
35
|
+
rdoc
|
36
|
+
spec/reports
|
37
|
+
test/tmp
|
38
|
+
test/version_tmp
|
39
|
+
tmp
|
40
|
+
tmtags
|
41
|
+
tramp
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2011-2013 Dan Sosedoff.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to
|
8
|
+
do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
14
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
15
|
+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
16
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
17
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
18
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/NEWS.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Capistrano Unicorn NEWS
|
2
|
+
|
3
|
+
## 0.2.0
|
4
|
+
|
5
|
+
Significant changes since 0.1.10 are as follows. Backwards-incompatible changes are **in bold**.
|
6
|
+
|
7
|
+
* Ensured `RAILS_ENV` is set correctly.
|
8
|
+
* Embedded multistage docs directly within the [README](README.md) (the wiki page was version-specific and misleading).
|
9
|
+
* Significantly tidied up the usage and documentation of configuration variables:
|
10
|
+
* **In most cases, it should now be sufficient to simply set `rails_env` correctly,
|
11
|
+
and other variables should assume the correct value by default.**
|
12
|
+
* **Make `unicorn_env` default to `rails_env` or `'production'`.**
|
13
|
+
* **Rename `app_env` to `unicorn_rack_env` and fix default value.**
|
14
|
+
* Add `unicorn_options` variable which allows passing of arbitrary options to unicorn.
|
15
|
+
* Added `app_subdir` to support app running in a subdirectory.
|
16
|
+
* Updated documentation in [README](README.md) to fix inaccuracies and ambiguities.
|
17
|
+
* `unicorn_pid` defaults to attempting to auto-detect from unicorn config file.
|
18
|
+
This avoids having to keep two paths in sync.
|
19
|
+
https://github.com/sosedoff/capistrano-unicorn/issues/7
|
20
|
+
* Also added the `unicorn:show_vars` task to make it easier to debug
|
21
|
+
config variable values client-side.
|
22
|
+
* Defer calculation of `unicorn-roles`.
|
23
|
+
|
24
|
+
It was noticed that there are a
|
25
|
+
[huge number of unmerged forks on github](https://github.com/sosedoff/capistrano-unicorn/issues/45),
|
26
|
+
so we also updated the [README](README.md) asking the community to
|
27
|
+
contribute back any useful changes they make.
|
data/README.md
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
# Capistrano Unicorn
|
2
|
+
|
3
|
+
Capistrano plugin that integrates Unicorn tasks into capistrano deployment script.
|
4
|
+
|
5
|
+
**Developers:** Please consider contributing your forked changes, or opening an
|
6
|
+
issue if there is no existing relevant one. There are a lot of forks--we'd love
|
7
|
+
to reabsorb some of the issues/solutions the community has encountered.
|
8
|
+
|
9
|
+
[![Build Status](https://travis-ci.org/sosedoff/capistrano-unicorn.png?branch=master)](https://travis-ci.org/sosedoff/capistrano-unicorn)
|
10
|
+
[![Gem Version](https://badge.fury.io/rb/capistrano-unicorn.png)](http://badge.fury.io/rb/capistrano-unicorn)
|
11
|
+
[![Code Climate](https://codeclimate.com/github/sosedoff/capistrano-unicorn.png)](https://codeclimate.com/github/sosedoff/capistrano-unicorn)
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
If you are upgrading from a previous version, please see the [NEWS file](NEWS.md).
|
16
|
+
|
17
|
+
### Setup
|
18
|
+
|
19
|
+
Add the library to your `Gemfile`:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
group :development do
|
23
|
+
gem 'capistrano-unicorn', :require => false
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
And load it into your deployment script `config/deploy.rb`:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'capistrano-unicorn'
|
31
|
+
```
|
32
|
+
|
33
|
+
Add unicorn restart task hook:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
after 'deploy:restart', 'unicorn:reload' # app IS NOT preloaded
|
37
|
+
after 'deploy:restart', 'unicorn:restart' # app preloaded
|
38
|
+
after 'deploy:restart', 'unicorn:duplicate' # before_fork hook implemented (zero downtime deployments)
|
39
|
+
```
|
40
|
+
|
41
|
+
Create a new configuration file `config/unicorn.rb` or `config/unicorn/STAGE.rb`,
|
42
|
+
where stage is your deployment environment.
|
43
|
+
|
44
|
+
Example config - [examples/rails3.rb](https://github.com/sosedoff/capistrano-unicorn/blob/master/examples/rails3.rb).
|
45
|
+
Please refer to Unicorn documentation for more examples and configuration options.
|
46
|
+
|
47
|
+
### Deploy
|
48
|
+
|
49
|
+
First, make sure you're running the latest release:
|
50
|
+
|
51
|
+
```
|
52
|
+
cap deploy
|
53
|
+
```
|
54
|
+
|
55
|
+
Then you can test each individual task:
|
56
|
+
|
57
|
+
```
|
58
|
+
cap unicorn:start
|
59
|
+
cap unicorn:stop
|
60
|
+
cap unicorn:reload
|
61
|
+
```
|
62
|
+
|
63
|
+
## Configuration
|
64
|
+
|
65
|
+
You can modify any of the following Capistrano variables in your `deploy.rb` config.
|
66
|
+
You can use the `unicorn:show_vars` task to check that the values you have specified
|
67
|
+
are set correctly.
|
68
|
+
|
69
|
+
### Environment parameters
|
70
|
+
|
71
|
+
- `unicorn_env` - Set basename of unicorn config `.rb` file to be used loaded from `unicorn_config_path`. Defaults to `rails_env` variable if set, otherwise `production`.
|
72
|
+
- `unicorn_rack_env` - Set the value which will be passed to unicorn via [the `-E` parameter as the Rack environment](http://unicorn.bogomips.org/unicorn_1.html). Valid values are `development`, `deployment`, and `none`. Defaults to `development` if `rails_env` is `development`, otherwise `deployment`.
|
73
|
+
|
74
|
+
### Execution parameters
|
75
|
+
|
76
|
+
- `unicorn_user` - Launch unicorn master as the specified user via `sudo`. Defaults to `nil`, which means no use of `sudo`, i.e. run as the user defined by the `user` variable.
|
77
|
+
- `unicorn_roles` - Define which roles to perform unicorn recipes on. Defaults to `:app`.
|
78
|
+
- `unicorn_bundle` - Set bundler command for unicorn. Defaults to `bundle`.
|
79
|
+
- `unicorn_bin` - Set unicorn executable file. Defaults to `unicorn`.
|
80
|
+
- `unicorn_options` - Set any additional options to be passed to unicorn on startup.
|
81
|
+
- `unicorn_restart_sleep_time` - Number of seconds to wait for (old) pidfile to show up when restarting unicorn. Defaults to 2.
|
82
|
+
|
83
|
+
### Relative path parameters
|
84
|
+
|
85
|
+
- `app_subdir` - If your app lives in a subdirectory 'rails' (say) of your repository, set this to `/rails` (the leading slash is required).
|
86
|
+
- `unicorn_config_rel_path` - Set the directory path (relative to `app_path` - see below) where unicorn config files reside. Defaults to `config`.
|
87
|
+
- `unicorn_config_filename` - Set the filename of the unicorn config file loaded from `unicorn_config_path`. Should not be present in multistage installations. Defaults to `unicorn.rb`.
|
88
|
+
|
89
|
+
### Absolute path parameters
|
90
|
+
|
91
|
+
- `app_path` - Set path to app root. Defaults to `current_path + app_subdir`.
|
92
|
+
- `unicorn_pid` - Set unicorn PID file path. By default, attempts to auto-detect from unicorn config file. On failure, falls back to value in `unicorn_default_pid`
|
93
|
+
- `unicorn_default_pid` - See above. Defaults to `#{current_path}/tmp/pids/unicorn.pid`
|
94
|
+
- `bundle_gemfile` - Set path to Gemfile. Defaults to `#{app_path}/Gemfile`
|
95
|
+
- `unicorn_config_path` - Set the directory where unicorn config files reside. Defaults to `#{current_path}/config`.
|
96
|
+
|
97
|
+
### Zero Downtime Deployment Options
|
98
|
+
|
99
|
+
* `unicorn:restart`: :-1: This can sort of support it with a configurable timeout, which may not be reliable.
|
100
|
+
* `unicorn:reload`: :question: Can anyone testify to its zero-downtime support?
|
101
|
+
* `unicorn:duplicate`: :+1: If you install the Unicorn `before_fork` hook, then yes! See: https://github.com/sosedoff/capistrano-unicorn/issues/40#issuecomment-16011353
|
102
|
+
|
103
|
+
## Available Tasks
|
104
|
+
|
105
|
+
To get a list of all capistrano tasks, run `cap -T`:
|
106
|
+
|
107
|
+
```
|
108
|
+
cap unicorn:add_worker # Add a new worker
|
109
|
+
cap unicorn:remove_worker # Remove amount of workers
|
110
|
+
cap unicorn:reload # Reload Unicorn
|
111
|
+
cap unicorn:restart # Restart Unicorn
|
112
|
+
cap unicorn:show_vars # Debug Unicorn variables
|
113
|
+
cap unicorn:shutdown # Immediately shutdown Unicorn
|
114
|
+
cap unicorn:start # Start Unicorn master process
|
115
|
+
cap unicorn:stop # Stop Unicorn
|
116
|
+
```
|
117
|
+
|
118
|
+
## Tests
|
119
|
+
|
120
|
+
To execute test suite run:
|
121
|
+
|
122
|
+
```
|
123
|
+
bundle exec rake test
|
124
|
+
```
|
125
|
+
|
126
|
+
### Multistage
|
127
|
+
|
128
|
+
The issue here is that capistrano loads default configuration and then
|
129
|
+
executes your staging task and overrides previously defined
|
130
|
+
variables. The default environment before executing your stage task is
|
131
|
+
set to `:production`, so it will use a wrong environment unless you
|
132
|
+
take steps to ensure that `:rails_env` and `:unicorn_env` are
|
133
|
+
set correctly.
|
134
|
+
|
135
|
+
Let's say you have a scenario involving two deployment stages: staging
|
136
|
+
and production. You’ll need to add `config/deploy/staging.rb` and
|
137
|
+
`config/deploy/production.rb` files. However, it makes sense to
|
138
|
+
adhere to DRY and avoid duplicating lines between the two files. So
|
139
|
+
it would be nicer to keep common settings in `config/deploy.rb`, and
|
140
|
+
only put stuff in each staging definition file which is really
|
141
|
+
specific to that staging environment. Fortunately this can be done
|
142
|
+
using the [lazy evaluation form of `set`](https://github.com/capistrano/capistrano/wiki/2.x-DSL-Configuration-Variables-Set).
|
143
|
+
|
144
|
+
So `config/deploy.rb` file would contain something like:
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
set :stages, %w(production staging)
|
148
|
+
set :default_stage, "staging"
|
149
|
+
require 'capistrano/ext/multistage'
|
150
|
+
|
151
|
+
role(:web) { domain }
|
152
|
+
role(:app) { domain }
|
153
|
+
role(:db, :primary => true) { domain }
|
154
|
+
|
155
|
+
set(:deploy_to) { "/home/#{user}/#{application}/#{fetch :rails_env}" }
|
156
|
+
set(:current_path) { File.join(deploy_to, current_dir) }
|
157
|
+
```
|
158
|
+
|
159
|
+
Then `config/deploy/production.rb` would contain something like:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
set :domain, "app.mydomain.com"
|
163
|
+
set :rails_env, "production"
|
164
|
+
```
|
165
|
+
|
166
|
+
and `config/deploy/staging.rb` would only need to contain something like:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
set :domain, "app.staging.mydomain.com"
|
170
|
+
set :rails_env, "staging"
|
171
|
+
```
|
172
|
+
|
173
|
+
Nice and clean!
|
174
|
+
|
175
|
+
## License
|
176
|
+
|
177
|
+
See LICENSE file for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/capistrano/unicorn/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "sepastian-capistrano3-unicorn"
|
6
|
+
spec.version = CapistranoUnicorn::VERSION.dup
|
7
|
+
spec.author = "Sebastian Gassner, Dan Sosedoff"
|
8
|
+
spec.email = "sebastian.gassner@gmail.com"
|
9
|
+
spec.homepage = "https://github.com/sepastian/capistrano-unicorn"
|
10
|
+
spec.summary = %q{Unicorn integration for Capistrano 3.x}
|
11
|
+
spec.description = %q{Capistrano 3.x plugin that integrates Unicorn server tasks.}
|
12
|
+
spec.license = "MIT"
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split("\n")
|
15
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_development_dependency "rake"
|
20
|
+
spec.add_development_dependency "unicorn"
|
21
|
+
spec.add_runtime_dependency "capistrano", "~> 3.0.0"
|
22
|
+
end
|
data/examples/rails3.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# ------------------------------------------------------------------------------
|
2
|
+
# Sample rails 3 config
|
3
|
+
# ------------------------------------------------------------------------------
|
4
|
+
|
5
|
+
# Set your full path to application.
|
6
|
+
app_path = "/path/to/app"
|
7
|
+
|
8
|
+
# Set unicorn options
|
9
|
+
worker_processes 1
|
10
|
+
preload_app true
|
11
|
+
timeout 180
|
12
|
+
listen "127.0.0.1:9000"
|
13
|
+
|
14
|
+
# Spawn unicorn master worker for user apps (group: apps)
|
15
|
+
user 'apps', 'apps'
|
16
|
+
|
17
|
+
# Fill path to your app
|
18
|
+
working_directory app_path
|
19
|
+
|
20
|
+
# Should be 'production' by default, otherwise use other env
|
21
|
+
rails_env = ENV['RAILS_ENV'] || 'production'
|
22
|
+
|
23
|
+
# Log everything to one file
|
24
|
+
stderr_path "log/unicorn.log"
|
25
|
+
stdout_path "log/unicorn.log"
|
26
|
+
|
27
|
+
# Set master PID location
|
28
|
+
pid "#{app_path}/tmp/pids/unicorn.pid"
|
29
|
+
|
30
|
+
before_fork do |server, worker|
|
31
|
+
ActiveRecord::Base.connection.disconnect!
|
32
|
+
|
33
|
+
old_pid = "#{server.config[:pid]}.oldbin"
|
34
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
35
|
+
begin
|
36
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
37
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
38
|
+
# someone else did our job for us
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
after_fork do |server, worker|
|
44
|
+
ActiveRecord::Base.establish_connection
|
45
|
+
end
|
File without changes
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
require 'capistrano/unicorn/utility'
|
3
|
+
|
4
|
+
include CapistranoUnicorn::Utility
|
5
|
+
|
6
|
+
# Load default values the capistrano 3.x way.
|
7
|
+
# See https://github.com/capistrano/capistrano/pull/605
|
8
|
+
namespace :load do
|
9
|
+
task :defaults do
|
10
|
+
|
11
|
+
# Environments
|
12
|
+
set :unicorn_env , Proc.new{ fetch(:rails_env, 'production') }
|
13
|
+
# Following recommendations from http://unicorn.bogomips.org/unicorn_1.html
|
14
|
+
set :unicorn_rack_env, Proc.new{ fetch(:rails_env) == 'development' ? 'development' : 'deployment' }
|
15
|
+
|
16
|
+
# Execution
|
17
|
+
set :unicorn_user , nil
|
18
|
+
set :unicorn_bundle , Proc.new{ fetch(:bundle_cmd, "bundle") }
|
19
|
+
set :unicorn_bin , "unicorn"
|
20
|
+
set :unicorn_options , ''
|
21
|
+
set :unicorn_restart_sleep_time, 2
|
22
|
+
|
23
|
+
# Relative paths
|
24
|
+
set :app_subdir , ''
|
25
|
+
set :unicorn_config_rel_path , "config"
|
26
|
+
set :unicorn_config_filename , "unicorn.rb"
|
27
|
+
set :unicorn_config_rel_file_path , Proc.new{ File.join(fetch(:unicorn_config_rel_path), fetch(:unicorn_config_filename)) }
|
28
|
+
set :unicorn_config_stage_rel_file_path, Proc.new{ File.join(fetch(:unicorn_config_rel_path), 'unicorn', "#{fetch(:unicorn_env)}.rb") }
|
29
|
+
|
30
|
+
# Absolute paths
|
31
|
+
# If you find the following confusing, try running 'cap unicorn:show_vars' -
|
32
|
+
# it might help :-)
|
33
|
+
set :app_path , Proc.new{ File.join(current_path, fetch(:app_subdir)) }
|
34
|
+
set :bundle_gemfile , Proc.new{ File.join(fetch(:app_path), 'Gemfile') }
|
35
|
+
set :unicorn_config_path , Proc.new{ File.join(fetch(:app_path), fetch(:unicorn_config_rel_path)) }
|
36
|
+
set :unicorn_config_file_path , Proc.new{ File.join(fetch(:app_path), fetch(:unicorn_config_rel_file_path)) }
|
37
|
+
set :unicorn_config_stage_file_path, Proc.new{ File.join(fetch(:app_path), fetch(:unicorn_config_stage_rel_file_path)) }
|
38
|
+
set :unicorn_default_pid , Proc.new{ File.join(fetch(:app_path), 'tmp', 'pids', 'unicorn.pid') }
|
39
|
+
set :unicorn_pid, Proc.new{
|
40
|
+
extracted_pid = extract_pid_file
|
41
|
+
if extracted_pid
|
42
|
+
extracted_pid
|
43
|
+
else
|
44
|
+
# TODO logger is not defined
|
45
|
+
#logger.important "err :: failed to auto-detect pid from #{local_unicorn_config}"
|
46
|
+
#logger.important "err :: falling back to default: #{unicorn_default_pid}"
|
47
|
+
fetch :unicorn_default_pid
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
namespace :unicorn do
|
54
|
+
desc 'Debug Unicorn variables'
|
55
|
+
task :show_vars do
|
56
|
+
on roles :app do
|
57
|
+
puts <<-EOF.gsub(/^ +/, '')
|
58
|
+
# Environments
|
59
|
+
rails_env #{fetch :rails_env}
|
60
|
+
unicorn_env #{fetch :unicorn_env}
|
61
|
+
unicorn_rack_env #{fetch :unicorn_rack_env}
|
62
|
+
|
63
|
+
# Execution
|
64
|
+
unicorn_user #{fetch(:unicorn_user).inspect}
|
65
|
+
unicorn_bundle #{fetch :unicorn_bundle}
|
66
|
+
unicorn_bin #{fetch :unicorn_bin}
|
67
|
+
unicorn_options #{fetch :unicorn_options}
|
68
|
+
unicorn_restart_sleep_time #{fetch :unicorn_restart_sleep_time}
|
69
|
+
|
70
|
+
# Relative paths
|
71
|
+
app_subdir #{fetch :app_subdir}
|
72
|
+
unicorn_config_rel_path #{fetch :unicorn_config_rel_path}
|
73
|
+
unicorn_config_filename #{fetch :unicorn_config_filename}
|
74
|
+
unicorn_config_rel_file_path #{fetch :unicorn_config_rel_file_path}
|
75
|
+
unicorn_config_stage_rel_file_path #{fetch :unicorn_config_stage_rel_file_path}
|
76
|
+
|
77
|
+
# Absolute paths
|
78
|
+
app_path #{fetch :app_path}
|
79
|
+
unicorn_pid #{fetch :unicorn_pid}
|
80
|
+
bundle_gemfile #{fetch :bundle_gemfile}
|
81
|
+
unicorn_config_path #{fetch :unicorn_config_path}
|
82
|
+
unicorn_config_file_path #{fetch :unicorn_config_file_path}
|
83
|
+
unicorn_config_stage_file_path
|
84
|
+
-> "#{fetch :unicorn_config_stage_file_path}
|
85
|
+
EOF
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
desc 'Start Unicorn master process'
|
90
|
+
task :start do
|
91
|
+
on roles unicorn_roles, :except => {:no_release => true} do
|
92
|
+
execute start_unicorn
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
desc 'Stop Unicorn'
|
97
|
+
task :stop do
|
98
|
+
on roles unicorn_roles, :except => {:no_release => true} do
|
99
|
+
execute kill_unicorn('QUIT')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
desc 'Immediately shutdown Unicorn'
|
104
|
+
task :shutdown do
|
105
|
+
on roles unicorn_roles, :except => {:no_release => true} do
|
106
|
+
execute kill_unicorn('TERM')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
desc 'Restart Unicorn'
|
111
|
+
task :restart do
|
112
|
+
on roles unicorn_roles, :except => {:no_release => true} do
|
113
|
+
execute duplicate_unicorn
|
114
|
+
execute :sleep, fetch(:unicorn_restart_sleep_time)
|
115
|
+
execute "if #{old_unicorn_is_running?}; then #{unicorn_send_signal('QUIT', get_old_unicorn_pid)}; fi;"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
desc 'Duplicate Unicorn'
|
120
|
+
task :duplicate do
|
121
|
+
on roles unicorn_roles, :except => {:no_release => true} do
|
122
|
+
execute duplicate_unicorn()
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
desc 'Reload Unicorn'
|
127
|
+
task :reload do
|
128
|
+
on roles => unicorn_roles, :except => {:no_release => true} do
|
129
|
+
execute "if #{unicorn_is_running?}; then #{unicorn_send_signal('HUP')}; else #{start_unicorn}; fi;"
|
130
|
+
# run <<-END
|
131
|
+
# if #{unicorn_is_running?}; then
|
132
|
+
# echo "Reloading Unicorn...";
|
133
|
+
# #{unicorn_send_signal('HUP')};
|
134
|
+
# else
|
135
|
+
# #{start_unicorn}
|
136
|
+
# fi;
|
137
|
+
# END
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
desc 'Add a new worker'
|
142
|
+
task :add_worker do
|
143
|
+
on roles => unicorn_roles, :except => {:no_release => true} do
|
144
|
+
execute "if #{unicorn_is_running?}; then #{unicorn_send_signal('TTIN')}; fi;"
|
145
|
+
# run <<-END
|
146
|
+
# if #{unicorn_is_running?}; then
|
147
|
+
# echo "Adding a new Unicorn worker...";
|
148
|
+
# #{unicorn_send_signal('TTIN')};
|
149
|
+
# else
|
150
|
+
# echo "Unicorn is not running.";
|
151
|
+
# fi;
|
152
|
+
# END
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
desc 'Remove amount of workers'
|
157
|
+
task :remove_worker do
|
158
|
+
on roles => unicorn_roles, :except => {:no_release => true} do
|
159
|
+
execute "if #{unicorn_is_running?}; then #{unicorn_send_signal('TTOU')}; fi;"
|
160
|
+
# run <<-END
|
161
|
+
# if #{unicorn_is_running?}; then
|
162
|
+
# echo "Removing a Unicorn worker...";
|
163
|
+
# #{unicorn_send_signal('TTOU')};
|
164
|
+
# else
|
165
|
+
# echo "Unicorn is not running.";
|
166
|
+
# fi;
|
167
|
+
# END
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.expand_path(File.join('..', 'tasks', 'unicorn.cap'), __FILE__)
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module CapistranoUnicorn
|
4
|
+
module Utility
|
5
|
+
# In Capistrano 3, shell scripts must be invoked with SSHKit's execute, instead of run.
|
6
|
+
# SSHKit will "sanitize" all multi-line commands (here docs), replacing "\n" with ";".
|
7
|
+
# Sanitizing renders some shell scripts illegal, for instance:
|
8
|
+
#
|
9
|
+
# if [ -e FILE ]; then
|
10
|
+
# echo "Found."
|
11
|
+
# fi
|
12
|
+
#
|
13
|
+
# This would become
|
14
|
+
#
|
15
|
+
# if [ -e FILE ]; then; echo "Found."; fi;
|
16
|
+
#
|
17
|
+
# which is illegal because of the ';' after 'then'.
|
18
|
+
#
|
19
|
+
# To avoid errors, replace all "\n" with " " in shell scripts,
|
20
|
+
# before SSHKit gets a chance to replace "\n" with ";"
|
21
|
+
def local_unicorn_config
|
22
|
+
if File.exist? fetch(:unicorn_config_rel_file_path)
|
23
|
+
fetch(:unicorn_config_rel_file_path)
|
24
|
+
else
|
25
|
+
fetch(:unicorn_config_stage_rel_file_path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_pid_file
|
30
|
+
tmp = Tempfile.new('unicorn.rb')
|
31
|
+
begin
|
32
|
+
conf = local_unicorn_config
|
33
|
+
tmp.write <<-EOF.gsub(/^ */, '')
|
34
|
+
config_file = "#{conf}"
|
35
|
+
|
36
|
+
# stub working_directory to avoid chdir failure since this will
|
37
|
+
# run client-side:
|
38
|
+
def working_directory(path); end
|
39
|
+
|
40
|
+
instance_eval(File.read(config_file), config_file) if config_file
|
41
|
+
puts set[:pid]
|
42
|
+
exit 0
|
43
|
+
EOF
|
44
|
+
tmp.close
|
45
|
+
extracted_pid = `unicorn -c "#{tmp.path}"`
|
46
|
+
$?.success? ? extracted_pid.rstrip : nil
|
47
|
+
rescue StandardError => e
|
48
|
+
return nil
|
49
|
+
ensure
|
50
|
+
tmp.close
|
51
|
+
tmp.unlink
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Check if a remote process exists using its pid file
|
56
|
+
#
|
57
|
+
def remote_process_exists?(pid_file)
|
58
|
+
"[ -e #{pid_file} ] && #{try_unicorn_user} kill -0 `cat #{pid_file}` > /dev/null 2>&1"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Stale Unicorn process pid file
|
62
|
+
#
|
63
|
+
def old_unicorn_pid
|
64
|
+
"#{fetch :unicorn_pid}.oldbin"
|
65
|
+
end
|
66
|
+
|
67
|
+
# Command to check if Unicorn is running
|
68
|
+
#
|
69
|
+
def unicorn_is_running?
|
70
|
+
remote_process_exists?(fetch :unicorn_pid)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Command to check if stale Unicorn is running
|
74
|
+
#
|
75
|
+
def old_unicorn_is_running?
|
76
|
+
remote_process_exists?(old_unicorn_pid)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Get unicorn master process PID (using the shell)
|
80
|
+
#
|
81
|
+
def get_unicorn_pid(pid_file=fetch(:unicorn_pid))
|
82
|
+
"`cat #{pid_file}`"
|
83
|
+
end
|
84
|
+
|
85
|
+
# Get unicorn master (old) process PID
|
86
|
+
#
|
87
|
+
def get_old_unicorn_pid
|
88
|
+
get_unicorn_pid(old_unicorn_pid)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Send a signal to a unicorn master processes
|
92
|
+
#
|
93
|
+
def unicorn_send_signal(signal, pid=get_unicorn_pid)
|
94
|
+
"#{try_unicorn_user} kill -s #{signal} #{pid}"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Run a command as the :unicorn_user user if :unicorn_user is a string.
|
98
|
+
# Otherwise run as default (:user) user.
|
99
|
+
#
|
100
|
+
def try_unicorn_user
|
101
|
+
"#{sudo :as => unicorn_user.to_s}" if fetch(:unicorn_user).kind_of?(String)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Kill Unicorns in multiple ways O_O
|
105
|
+
#
|
106
|
+
def kill_unicorn(signal)
|
107
|
+
script = <<-END
|
108
|
+
if #{unicorn_is_running?}; then
|
109
|
+
echo "Stopping Unicorn...";
|
110
|
+
#{unicorn_send_signal(signal)};
|
111
|
+
else
|
112
|
+
echo "Unicorn is not running.";
|
113
|
+
fi;
|
114
|
+
END
|
115
|
+
script.split.join(' ')
|
116
|
+
end
|
117
|
+
|
118
|
+
# Start the Unicorn server
|
119
|
+
#
|
120
|
+
def start_unicorn
|
121
|
+
%Q%
|
122
|
+
if [ -e "#{fetch :unicorn_config_file_path}" ]; then
|
123
|
+
UNICORN_CONFIG_PATH=#{fetch :unicorn_config_file_path};
|
124
|
+
else
|
125
|
+
if [ -e "#{fetch :unicorn_config_stage_file_path}" ]; then
|
126
|
+
UNICORN_CONFIG_PATH=#{fetch :unicorn_config_stage_file_path};
|
127
|
+
else
|
128
|
+
echo "Config file for "#{fetch :unicorn_env}" environment was not found at either "#{fetch :unicorn_config_file_path}" or "#{fetch :unicorn_config_stage_file_path}"";
|
129
|
+
exit 1;
|
130
|
+
fi;
|
131
|
+
fi;
|
132
|
+
|
133
|
+
if [ -e "#{fetch :unicorn_pid}" ]; then
|
134
|
+
if #{try_unicorn_user} kill -0 `cat #{fetch :unicorn_pid}` > /dev/null 2>&1; then
|
135
|
+
echo "Unicorn is already running!";
|
136
|
+
exit 0;
|
137
|
+
fi;
|
138
|
+
|
139
|
+
#{try_unicorn_user} rm #{fetch :unicorn_pid};
|
140
|
+
fi;
|
141
|
+
|
142
|
+
echo "Starting Unicorn...";
|
143
|
+
cd #{fetch :app_path} && #{try_unicorn_user} RAILS_ENV=#{fetch :rails_env} BUNDLE_GEMFILE=#{fetch :bundle_gemfile} #{fetch :unicorn_bundle} exec #{fetch :unicorn_bin} -c $UNICORN_CONFIG_PATH -E #{fetch :unicorn_rack_env} -D #{fetch :unicorn_options};
|
144
|
+
%.split.join(' ')
|
145
|
+
end
|
146
|
+
|
147
|
+
def duplicate_unicorn
|
148
|
+
script = <<-END
|
149
|
+
if #{unicorn_is_running?}; then
|
150
|
+
echo "Duplicating Unicorn...";
|
151
|
+
#{unicorn_send_signal('USR2')};
|
152
|
+
else
|
153
|
+
#{start_unicorn}
|
154
|
+
fi;
|
155
|
+
END
|
156
|
+
script.split.join(' ')
|
157
|
+
end
|
158
|
+
|
159
|
+
def unicorn_roles
|
160
|
+
# TODO proc necessary here?
|
161
|
+
Proc.new{ fetch(:unicorn_roles, :app) }.call
|
162
|
+
#defer{ fetch(:unicorn_roles, :app) }
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
data/lib/unicorn.rb
ADDED
File without changes
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe CapistranoUnicorn::CapistranoIntegration, "loaded tasks into capistrano" do
|
4
|
+
before do
|
5
|
+
@configuration = Capistrano::Configuration.new
|
6
|
+
@configuration.extend(Capistrano::Spec::ConfigurationExtension)
|
7
|
+
CapistranoUnicorn::CapistranoIntegration.load_into(@configuration)
|
8
|
+
end
|
9
|
+
|
10
|
+
shared_examples_for "a task" do |task_name|
|
11
|
+
it "sets attributes in before_task hook" do
|
12
|
+
# Environments
|
13
|
+
@configuration.should_receive(:_cset).with(:unicorn_env)
|
14
|
+
@configuration.should_receive(:_cset).with(:unicorn_rack_env)
|
15
|
+
|
16
|
+
# Execution
|
17
|
+
@configuration.should_receive(:_cset).with(:unicorn_user)
|
18
|
+
@configuration.should_receive(:_cset).with(:unicorn_bundle)
|
19
|
+
@configuration.should_receive(:_cset).with(:unicorn_bin)
|
20
|
+
@configuration.should_receive(:_cset).with(:unicorn_options)
|
21
|
+
@configuration.should_receive(:_cset).with(:unicorn_restart_sleep_time)
|
22
|
+
|
23
|
+
# Relative paths
|
24
|
+
@configuration.should_receive(:_cset).with(:app_subdir)
|
25
|
+
@configuration.should_receive(:_cset).with(:unicorn_config_rel_path)
|
26
|
+
@configuration.should_receive(:_cset).with(:unicorn_config_filename)
|
27
|
+
@configuration.should_receive(:_cset).with(:unicorn_config_rel_file_path)
|
28
|
+
@configuration.should_receive(:_cset).with(:unicorn_config_stage_rel_file_path)
|
29
|
+
|
30
|
+
# Absolute paths
|
31
|
+
@configuration.should_receive(:_cset).with(:app_path)
|
32
|
+
@configuration.should_receive(:_cset).with(:unicorn_pid)
|
33
|
+
@configuration.should_receive(:_cset).with(:bundle_gemfile)
|
34
|
+
@configuration.should_receive(:_cset).with(:unicorn_config_path)
|
35
|
+
@configuration.should_receive(:_cset).with(:unicorn_config_file_path)
|
36
|
+
@configuration.should_receive(:_cset).with(:unicorn_config_stage_file_path)
|
37
|
+
|
38
|
+
@configuration.find_and_execute_task(task_name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "task" do
|
43
|
+
describe 'unicorn:start' do
|
44
|
+
before do
|
45
|
+
@configuration.stub(:start_unicorn)
|
46
|
+
@configuration.stub(:_cset)
|
47
|
+
end
|
48
|
+
|
49
|
+
it_behaves_like "a task", 'unicorn:start'
|
50
|
+
|
51
|
+
it "runs start_unicorn command" do
|
52
|
+
@configuration.should_receive(:start_unicorn).and_return("start unicorn command")
|
53
|
+
@configuration.find_and_execute_task('unicorn:start')
|
54
|
+
@configuration.should have_run("start unicorn command")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'unicorn:stop' do
|
59
|
+
before do
|
60
|
+
@configuration.stub(:kill_unicorn)
|
61
|
+
@configuration.stub(:_cset)
|
62
|
+
end
|
63
|
+
|
64
|
+
it_behaves_like "a task", 'unicorn:stop'
|
65
|
+
|
66
|
+
it "runs kill_unicorn command" do
|
67
|
+
@configuration.should_receive(:kill_unicorn).with('QUIT').and_return("kill unicorn command")
|
68
|
+
@configuration.find_and_execute_task('unicorn:stop')
|
69
|
+
@configuration.should have_run("kill unicorn command")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#kill_unicorn" do
|
75
|
+
before do
|
76
|
+
@configuration.stub(:unicorn_pid).and_return(999)
|
77
|
+
@configuration.stub(:unicorn_user).and_return("deploy_user")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "generates the kill unicorn command" do
|
81
|
+
@configuration.kill_unicorn('QUIT').should match /-u deploy_user kill -s QUIT `cat 999`;/
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe CapistranoUnicorn::Config, "loaded into a configuration" do
|
3
|
+
before do
|
4
|
+
@configuration = Capistrano::Configuration.new
|
5
|
+
@configuration.extend(Capistrano::Spec::ConfigurationExtension)
|
6
|
+
CapistranoUnicorn::CapistranoIntegration.load_into(@configuration)
|
7
|
+
end
|
8
|
+
|
9
|
+
context "testing variables" do
|
10
|
+
before do
|
11
|
+
# define _cset etc. from capistrano
|
12
|
+
@configuration.load 'deploy'
|
13
|
+
|
14
|
+
# capistrano-unicorn variables are set during a 'before'
|
15
|
+
# callback, so in order to be able to test the result, we need
|
16
|
+
# to ensure the callback is triggered.
|
17
|
+
@configuration.trigger :before
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "app paths" do
|
21
|
+
cur_path = '/path/to/myapp'
|
22
|
+
|
23
|
+
before do
|
24
|
+
@configuration.set(:current_path, cur_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
shared_examples_for "an app in path" do |app_path|
|
28
|
+
let(:shell) { :` } # ` } work around confused emacs ruby-mode
|
29
|
+
|
30
|
+
specify "app_path should default to #{app_path}" do
|
31
|
+
@configuration.fetch(:app_path).should == app_path
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should default to a sensible pid file when auto-detection failed" do
|
35
|
+
@configuration.should_receive(shell).with(/unicorn -c /).and_return('') do |cmd|
|
36
|
+
`false` # Simulate failure by setting $?
|
37
|
+
end
|
38
|
+
@configuration.logger.stub(:important)
|
39
|
+
@configuration.fetch(:unicorn_pid).should == app_path + "/tmp/pids/unicorn.pid"
|
40
|
+
end
|
41
|
+
|
42
|
+
shared_examples "auto-detect pid file from unicorn config" do
|
43
|
+
|pid_file, primary_exists, config_file|
|
44
|
+
which_config = primary_exists ? 'primary' : 'stage'
|
45
|
+
it "should auto-detect pid file from #{which_config} unicorn config" do
|
46
|
+
# Tempfile.new in Ruby 1.9.2 will call File.exist?
|
47
|
+
allow(File).to receive(:exist?).with(/tmp/)
|
48
|
+
|
49
|
+
File.should_receive(:exist?).with('config/unicorn.rb').and_return(primary_exists)
|
50
|
+
tmpfile = nil
|
51
|
+
@configuration.should_receive(shell).with(/unicorn -c /) do |cmd|
|
52
|
+
(cmd =~ /^unicorn -c "(.+)"$/).should be_true
|
53
|
+
tmpfile = $~[1]
|
54
|
+
tmpfile.should include("tmp")
|
55
|
+
File.read(tmpfile).should include(%!config_file = "#{config_file}"!)
|
56
|
+
`true` # Simulate success by setting $?
|
57
|
+
pid_file
|
58
|
+
end
|
59
|
+
@configuration.fetch(:unicorn_pid).should == pid_file
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
include_examples "auto-detect pid file from unicorn config", \
|
64
|
+
'/path/to/pid/from/config/file', true, "config/unicorn.rb"
|
65
|
+
|
66
|
+
include_examples "auto-detect pid file from unicorn config", \
|
67
|
+
'/path/to/pid/from/stage/config/file', false, "config/unicorn/production.rb"
|
68
|
+
|
69
|
+
specify "Gemfile should default correctly" do
|
70
|
+
@configuration.fetch(:bundle_gemfile).should == app_path + "/Gemfile"
|
71
|
+
end
|
72
|
+
|
73
|
+
specify "config/ directory should default correctly" do
|
74
|
+
@configuration.fetch(:unicorn_config_path).should == app_path + "/config"
|
75
|
+
end
|
76
|
+
|
77
|
+
specify "config file should default correctly" do
|
78
|
+
@configuration.fetch(:unicorn_config_file_path).should == app_path + "/config/unicorn.rb"
|
79
|
+
end
|
80
|
+
|
81
|
+
specify "per-stage config file should default correctly" do
|
82
|
+
@configuration.fetch(:unicorn_config_stage_file_path).should == app_path + "/config/unicorn/production.rb"
|
83
|
+
end
|
84
|
+
|
85
|
+
specify "per-stage config file should be set correctly for different environment" do
|
86
|
+
@configuration.set(:rails_env, 'staging')
|
87
|
+
@configuration.fetch(:unicorn_config_stage_file_path).should == app_path + "/config/unicorn/staging.rb"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "app in current_path" do
|
92
|
+
it_should_behave_like "an app in path", cur_path
|
93
|
+
end
|
94
|
+
|
95
|
+
context "app in a subdirectory" do
|
96
|
+
subdir = 'mysubdir'
|
97
|
+
|
98
|
+
before do
|
99
|
+
@configuration.set(:app_subdir, '/' + subdir)
|
100
|
+
end
|
101
|
+
|
102
|
+
it_should_behave_like "an app in path", cur_path + '/' + subdir
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "unicorn_env" do
|
107
|
+
it "should default to value of rails_env if set" do
|
108
|
+
@configuration.set(:rails_env, 'staging')
|
109
|
+
@configuration.fetch(:unicorn_env).should == \
|
110
|
+
@configuration.fetch(:rails_env)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should default to production if rails_env not set" do
|
114
|
+
@configuration.fetch(:unicorn_env).should == 'production'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "unicorn_rack_env" do
|
119
|
+
it "should default to deployment if rails_env not set" do
|
120
|
+
@configuration.fetch(:unicorn_rack_env).should == 'deployment'
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should default to development if rails_env set to development" do
|
124
|
+
@configuration.set(:rails_env, 'development')
|
125
|
+
@configuration.fetch(:unicorn_rack_env).should == 'development'
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should default to deployment if rails_env set to anything else" do
|
129
|
+
@configuration.set(:rails_env, 'staging')
|
130
|
+
@configuration.fetch(:unicorn_rack_env).should == 'deployment'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sepastian-capistrano3-unicorn
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sebastian Gassner, Dan Sosedoff
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-22 00:00:00.000000000 Z
|
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'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: unicorn
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
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: 3.0.0
|
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: 3.0.0
|
62
|
+
description: Capistrano 3.x plugin that integrates Unicorn server tasks.
|
63
|
+
email: sebastian.gassner@gmail.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- .gitignore
|
69
|
+
- .rspec
|
70
|
+
- .travis.yml
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE
|
73
|
+
- NEWS.md
|
74
|
+
- README.md
|
75
|
+
- Rakefile
|
76
|
+
- capistrano-unicorn.gemspec
|
77
|
+
- examples/rails3.rb
|
78
|
+
- lib/capistrano-unicorn.rb
|
79
|
+
- lib/capistrano/tasks/unicorn.cap
|
80
|
+
- lib/capistrano/unicorn.rb
|
81
|
+
- lib/capistrano/unicorn/utility.rb
|
82
|
+
- lib/capistrano/unicorn/version.rb
|
83
|
+
- lib/unicorn.rb
|
84
|
+
- spec/capistrano_integration_spec.rb
|
85
|
+
- spec/config_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
homepage: https://github.com/sepastian/capistrano-unicorn
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 1.8.23
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: Unicorn integration for Capistrano 3.x
|
112
|
+
test_files: []
|
113
|
+
has_rdoc:
|