capistrano-unicorn-sic 0.3.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8091b3b6283213655531467af348b2559f93a0fa
4
+ data.tar.gz: 2cf9717de5125c0c81af464b93fe7a4bd78dfa0a
5
+ SHA512:
6
+ metadata.gz: fa9cde766ec7c9eef970fcd877489d5c63a69ba85f05bad4ce816f86f1ad37054ff804b5ea53b9a970b2a9b37c5338170a920540a0ad623b97df003d9d5b1c30
7
+ data.tar.gz: c66ff4d5b531c2768b92f1627fa06b027ee5ed4db1cb0255cc2761842574c82cf3f174aeb969b8bb0a3316e3848fd398b69082c10b86c8f00c847ab326cb58ca
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
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=documentation
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rspec'
7
+ gem 'capistrano-spec'
8
+ gem 'pry-debugger'
9
+ end
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,178 @@
1
+ # Capistrano Unicorn
2
+
3
+ Capistrano 3.x plugin that integrates Unicorn tasks into capistrano deployment script.
4
+ Taken from https://github.com/sosedoff/capistrano-unicorn and adapted to work with Capistrano 3.x.
5
+
6
+ **Note: this code is not well tested, if anything fails, please report it. Use at your own risk.**
7
+
8
+ **Developers:** Please consider contributing your forked changes, or opening an
9
+ issue if there is no existing relevant one. There are a lot of forks--we'd love
10
+ to reabsorb some of the issues/solutions the community has encountered.
11
+
12
+ [![Gem Version](https://badge.fury.io/rb/sepastian-capistrano3-unicorn.png)](http://badge.fury.io/rb/sepastian-capistrano3-unicorn)
13
+
14
+ ## Usage
15
+
16
+ If you are upgrading from a previous version, please see the [NEWS file](NEWS.md).
17
+
18
+ ### Setup
19
+
20
+ Add the library to your `Gemfile`:
21
+
22
+ ```ruby
23
+ group :development do
24
+ gem 'sepastian-capistrano3-unicorn', :require => false
25
+ end
26
+ ```
27
+
28
+ And load it into your deployment script `config/deploy.rb`:
29
+
30
+ ```ruby
31
+ require 'capistrano/unicorn'
32
+ ```
33
+
34
+ Add unicorn restart task hook:
35
+
36
+ ```ruby
37
+ after 'deploy:restart', 'unicorn:reload' # app IS NOT preloaded
38
+ after 'deploy:restart', 'unicorn:restart' # app preloaded
39
+ after 'deploy:restart', 'unicorn:duplicate' # before_fork hook implemented (zero downtime deployments)
40
+ ```
41
+
42
+ Create a new configuration file `config/unicorn.rb` or `config/unicorn/STAGE.rb`,
43
+ where stage is your deployment environment.
44
+
45
+ Example config - [examples/rails3.rb](https://github.com/sosedoff/capistrano-unicorn/blob/master/examples/rails3.rb).
46
+ Please refer to Unicorn documentation for more examples and configuration options.
47
+
48
+ ### Deploy
49
+
50
+ First, make sure you're running the latest release:
51
+
52
+ ```
53
+ cap deploy
54
+ ```
55
+
56
+ Then you can test each individual task:
57
+
58
+ ```
59
+ cap unicorn:start
60
+ cap unicorn:stop
61
+ cap unicorn:reload
62
+ ```
63
+
64
+ ## Configuration
65
+
66
+ You can modify any of the following Capistrano variables in your `deploy.rb` config.
67
+ You can use the `unicorn:show_vars` task to check that the values you have specified
68
+ are set correctly.
69
+
70
+ ### Environment parameters
71
+
72
+ - `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`.
73
+ - `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`.
74
+
75
+ ### Execution parameters
76
+
77
+ - `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.
78
+ - `unicorn_roles` - Define which roles to perform unicorn recipes on. Defaults to `:app`.
79
+ - `unicorn_bundle` - Set bundler command for unicorn. Defaults to `bundle`.
80
+ - `unicorn_bin` - Set unicorn executable file. Defaults to `unicorn`.
81
+ - `unicorn_options` - Set any additional options to be passed to unicorn on startup.
82
+ - `unicorn_restart_sleep_time` - Number of seconds to wait for (old) pidfile to show up when restarting unicorn. Defaults to 2.
83
+
84
+ ### Relative path parameters
85
+
86
+ - `app_subdir` - If your app lives in a subdirectory 'rails' (say) of your repository, set this to `/rails` (the leading slash is required).
87
+ - `unicorn_config_rel_path` - Set the directory path (relative to `app_path` - see below) where unicorn config files reside. Defaults to `config`.
88
+ - `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`.
89
+
90
+ ### Absolute path parameters
91
+
92
+ - `app_path` - Set path to app root. Defaults to `current_path + app_subdir`.
93
+ - `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`
94
+ - `unicorn_default_pid` - See above. Defaults to `#{current_path}/tmp/pids/unicorn.pid`
95
+ - `bundle_gemfile` - Set path to Gemfile. Defaults to `#{app_path}/Gemfile`
96
+ - `unicorn_config_path` - Set the directory where unicorn config files reside. Defaults to `#{current_path}/config`.
97
+
98
+ ### Zero Downtime Deployment Options
99
+
100
+ * `unicorn:restart`: :-1: This can sort of support it with a configurable timeout, which may not be reliable.
101
+ * `unicorn:reload`: :question: Can anyone testify to its zero-downtime support?
102
+ * `unicorn:duplicate`: :+1: If you install the Unicorn `before_fork` hook, then yes! See: https://github.com/sosedoff/capistrano-unicorn/issues/40#issuecomment-16011353
103
+
104
+ ## Available Tasks
105
+
106
+ To get a list of all capistrano tasks, run `cap -T`:
107
+
108
+ ```
109
+ cap unicorn:add_worker # Add a new worker
110
+ cap unicorn:remove_worker # Remove amount of workers
111
+ cap unicorn:reload # Reload Unicorn
112
+ cap unicorn:restart # Restart Unicorn
113
+ cap unicorn:show_vars # Debug Unicorn variables
114
+ cap unicorn:shutdown # Immediately shutdown Unicorn
115
+ cap unicorn:start # Start Unicorn master process
116
+ cap unicorn:stop # Stop Unicorn
117
+ ```
118
+
119
+ ## Tests
120
+
121
+ To execute test suite run:
122
+
123
+ ```
124
+ bundle exec rake test
125
+ ```
126
+
127
+ ### Multistage
128
+
129
+ The issue here is that capistrano loads default configuration and then
130
+ executes your staging task and overrides previously defined
131
+ variables. The default environment before executing your stage task is
132
+ set to `:production`, so it will use a wrong environment unless you
133
+ take steps to ensure that `:rails_env` and `:unicorn_env` are
134
+ set correctly.
135
+
136
+ Let's say you have a scenario involving two deployment stages: staging
137
+ and production. You’ll need to add `config/deploy/staging.rb` and
138
+ `config/deploy/production.rb` files. However, it makes sense to
139
+ adhere to DRY and avoid duplicating lines between the two files. So
140
+ it would be nicer to keep common settings in `config/deploy.rb`, and
141
+ only put stuff in each staging definition file which is really
142
+ specific to that staging environment. Fortunately this can be done
143
+ using the [lazy evaluation form of `set`](https://github.com/capistrano/capistrano/wiki/2.x-DSL-Configuration-Variables-Set).
144
+
145
+ So `config/deploy.rb` file would contain something like:
146
+
147
+ ```ruby
148
+ set :stages, %w(production staging)
149
+ set :default_stage, "staging"
150
+ require 'capistrano/ext/multistage'
151
+
152
+ role(:web) { domain }
153
+ role(:app) { domain }
154
+ role(:db, :primary => true) { domain }
155
+
156
+ set(:deploy_to) { "/home/#{user}/#{application}/#{fetch :rails_env}" }
157
+ set(:current_path) { File.join(deploy_to, current_dir) }
158
+ ```
159
+
160
+ Then `config/deploy/production.rb` would contain something like:
161
+
162
+ ```ruby
163
+ set :domain, "app.mydomain.com"
164
+ set :rails_env, "production"
165
+ ```
166
+
167
+ and `config/deploy/staging.rb` would only need to contain something like:
168
+
169
+ ```ruby
170
+ set :domain, "app.staging.mydomain.com"
171
+ set :rails_env, "staging"
172
+ ```
173
+
174
+ Nice and clean!
175
+
176
+ ## License
177
+
178
+ See LICENSE file for details.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler"
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+
6
+ RSpec::Core::RakeTask.new(:test) do |spec|
7
+ spec.pattern = "spec/**/*_spec.rb"
8
+ end
9
+
10
+ task :default => :test
@@ -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 = "capistrano-unicorn-sic"
6
+ spec.version = CapistranoUnicorn::VERSION.dup
7
+ spec.author = "Sebastian Gassner, Dan Sosedoff, Florian Schwab"
8
+ spec.email = "sebastian.gassner@gmail.com"
9
+ spec.homepage = "https://github.com/SICSoftwareGmbH/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
@@ -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,155 @@
1
+ require 'capistrano/unicorn/utility'
2
+
3
+ include CapistranoUnicorn::Utility
4
+
5
+ # Load default values the capistrano 3.x way.
6
+ # See https://github.com/capistrano/capistrano/pull/605
7
+ namespace :load do
8
+ task :defaults do
9
+
10
+ # Environments
11
+ set :unicorn_env , Proc.new{ fetch(:rails_env, 'production') }
12
+ # Following recommendations from http://unicorn.bogomips.org/unicorn_1.html
13
+ set :unicorn_rack_env, Proc.new{ fetch(:rails_env) == 'development' ? 'development' : 'deployment' }
14
+
15
+ # Execution
16
+ set :unicorn_user , nil
17
+ set :unicorn_bundle , Proc.new{ fetch(:bundle_cmd, "bundle") }
18
+ set :unicorn_bin , "unicorn"
19
+ set :unicorn_options , ''
20
+ set :unicorn_restart_sleep_time, 2
21
+
22
+ # Relative paths
23
+ set :app_subdir , ''
24
+ set :unicorn_config_rel_path , "config"
25
+ set :unicorn_config_filename , "unicorn.rb"
26
+ set :unicorn_config_rel_file_path , Proc.new{ File.join(fetch(:unicorn_config_rel_path), fetch(:unicorn_config_filename)) }
27
+ set :unicorn_config_stage_rel_file_path, Proc.new{ File.join(fetch(:unicorn_config_rel_path), 'unicorn', "#{fetch(:unicorn_env)}.rb") }
28
+
29
+ # Absolute paths
30
+ # If you find the following confusing, try running 'cap unicorn:show_vars' -
31
+ # it might help :-)
32
+ set :app_path , Proc.new{ File.join(current_path, fetch(:app_subdir)) }
33
+ set :unicorn_config_path , Proc.new{ File.join(fetch(:app_path), fetch(:unicorn_config_rel_path)) }
34
+ set :unicorn_config_file_path , Proc.new{ File.join(fetch(:app_path), fetch(:unicorn_config_rel_file_path)) }
35
+ set :unicorn_config_stage_file_path, Proc.new{ File.join(fetch(:app_path), fetch(:unicorn_config_stage_rel_file_path)) }
36
+ set :unicorn_default_pid , Proc.new{ File.join(fetch(:app_path), 'tmp', 'pids', 'unicorn.pid') }
37
+ set :unicorn_pid, Proc.new{
38
+ extracted_pid = extract_pid_file
39
+ if extracted_pid
40
+ extracted_pid
41
+ else
42
+ # TODO logger is not defined
43
+ #logger.important "err :: failed to auto-detect pid from #{local_unicorn_config}"
44
+ #logger.important "err :: falling back to default: #{unicorn_default_pid}"
45
+ fetch :unicorn_default_pid
46
+ end
47
+ }
48
+ end
49
+ end
50
+
51
+ namespace :unicorn do
52
+ desc 'Debug Unicorn variables'
53
+ task :show_vars do
54
+ on roles :app do
55
+ puts <<-EOF.gsub(/^ +/, '')
56
+ # Environments
57
+ rails_env #{fetch :rails_env}
58
+ unicorn_env #{fetch :unicorn_env}
59
+ unicorn_rack_env #{fetch :unicorn_rack_env}
60
+
61
+ # Execution
62
+ unicorn_user #{fetch(:unicorn_user).inspect}
63
+ unicorn_bundle #{fetch :unicorn_bundle}
64
+ unicorn_bin #{fetch :unicorn_bin}
65
+ unicorn_options #{fetch :unicorn_options}
66
+ unicorn_restart_sleep_time #{fetch :unicorn_restart_sleep_time}
67
+
68
+ # Relative paths
69
+ app_subdir #{fetch :app_subdir}
70
+ unicorn_config_rel_path #{fetch :unicorn_config_rel_path}
71
+ unicorn_config_filename #{fetch :unicorn_config_filename}
72
+ unicorn_config_rel_file_path #{fetch :unicorn_config_rel_file_path}
73
+ unicorn_config_stage_rel_file_path #{fetch :unicorn_config_stage_rel_file_path}
74
+
75
+ # Absolute paths
76
+ app_path #{fetch :app_path}
77
+ unicorn_pid #{fetch :unicorn_pid}
78
+ #bundle_gemfile #{fetch :bundle_gemfile}
79
+ unicorn_config_path #{fetch :unicorn_config_path}
80
+ unicorn_config_file_path #{fetch :unicorn_config_file_path}
81
+ unicorn_config_stage_file_path
82
+ -> "#{fetch :unicorn_config_stage_file_path}
83
+ EOF
84
+ end
85
+ end
86
+
87
+ desc 'Start Unicorn master process'
88
+ task :start do
89
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
90
+ execute start_unicorn
91
+ end
92
+ end
93
+
94
+ desc 'Stop Unicorn'
95
+ task :stop do
96
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
97
+ execute kill_unicorn('QUIT')
98
+ end
99
+ end
100
+
101
+ desc 'Immediately shutdown Unicorn'
102
+ task :shutdown do
103
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
104
+ execute kill_unicorn('TERM')
105
+ end
106
+ end
107
+
108
+ desc 'Restart Unicorn'
109
+ task :restart do
110
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
111
+ duplicate_unicorn
112
+ execute :sleep, fetch(:unicorn_restart_sleep_time)
113
+
114
+ if old_unicorn_is_running?
115
+ unicorn_send_signal('QUIT', get_old_unicorn_pid)
116
+ end
117
+ end
118
+ end
119
+
120
+ desc 'Duplicate Unicorn'
121
+ task :duplicate do
122
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
123
+ duplicate_unicorn
124
+ end
125
+ end
126
+
127
+ desc 'Reload Unicorn'
128
+ task :reload do
129
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
130
+ if unicorn_is_running?
131
+ unicorn_send_signal('HUP')
132
+ else
133
+ start_unicorn
134
+ end
135
+ end
136
+ end
137
+
138
+ desc 'Add a new worker'
139
+ task :add_worker do
140
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
141
+ if unicorn_is_running?
142
+ unicorn_send_signal('TTIN')
143
+ end
144
+ end
145
+ end
146
+
147
+ desc 'Remove amount of workers'
148
+ task :remove_worker do
149
+ on roles unicorn_roles, reject: lambda { |h| h.properties.no_release } do
150
+ if unicorn_is_running?
151
+ unicorn_send_signal('TTOU')
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1 @@
1
+ load File.expand_path(File.join('..', 'tasks', 'unicorn.cap'), __FILE__)
@@ -0,0 +1,149 @@
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
+ def local_unicorn_config
7
+ if File.exist? fetch(:unicorn_config_rel_file_path)
8
+ fetch(:unicorn_config_rel_file_path)
9
+ else
10
+ fetch(:unicorn_config_stage_rel_file_path)
11
+ end
12
+ end
13
+
14
+ def extract_pid_file
15
+ tmp = Tempfile.new('unicorn.rb')
16
+ begin
17
+ conf = local_unicorn_config
18
+ tmp.write <<-EOF.gsub(/^ */, '')
19
+ config_file = "#{conf}"
20
+
21
+ # stub working_directory to avoid chdir failure since this will
22
+ # run client-side:
23
+ def working_directory(path); end
24
+
25
+ instance_eval(File.read(config_file), config_file) if config_file
26
+ puts set[:pid]
27
+ exit 0
28
+ EOF
29
+ tmp.close
30
+ extracted_pid = `unicorn -c "#{tmp.path}"`
31
+ $?.success? ? extracted_pid.rstrip : nil
32
+ rescue StandardError => e
33
+ return nil
34
+ ensure
35
+ tmp.close
36
+ tmp.unlink
37
+ end
38
+ end
39
+
40
+ # Check if a remote process exists using its pid file
41
+ #
42
+ def remote_process_exists?(pid_file)
43
+ test("[ -e #{pid_file} ]") && unicorn_execute(:kill, '-0', "`cat #{pid_file}`", '> /dev/null 2>&1', raise_on_non_zero_exit: false)
44
+ end
45
+
46
+ # Stale Unicorn process pid file
47
+ #
48
+ def old_unicorn_pid
49
+ "#{fetch :unicorn_pid}.oldbin"
50
+ end
51
+
52
+ # Command to check if Unicorn is running
53
+ #
54
+ def unicorn_is_running?
55
+ remote_process_exists?(fetch(:unicorn_pid))
56
+ end
57
+
58
+ # Command to check if stale Unicorn is running
59
+ #
60
+ def old_unicorn_is_running?
61
+ remote_process_exists?(old_unicorn_pid)
62
+ end
63
+
64
+ # Get unicorn master process PID (using the shell)
65
+ #
66
+ def get_unicorn_pid(pid_file=fetch(:unicorn_pid))
67
+ capture "cat #{pid_file}"
68
+ end
69
+
70
+ # Get unicorn master (old) process PID
71
+ #
72
+ def get_old_unicorn_pid
73
+ get_unicorn_pid(old_unicorn_pid)
74
+ end
75
+
76
+ # Send a signal to a unicorn master processes
77
+ #
78
+ def unicorn_send_signal(signal, pid=get_unicorn_pid)
79
+ unicorn_execute 'kill', '-s', signal, pid
80
+ end
81
+
82
+ # Run a unicorn command with or without sudo
83
+ # Run a command as the :unicorn_user user if :unicorn_user is a string.
84
+ # Otherwise run as default (:user) user.
85
+ #
86
+ def unicorn_execute(*args)
87
+ options = args.extract_options!
88
+
89
+ command = "bash -l -c \"#{args.join(' ')}\""
90
+ if unicorn_user = fetch(:unicorn_user)
91
+ execute :sudo, '-u', unicorn_user, command, options
92
+ else
93
+ execute command, options
94
+ end
95
+ end
96
+
97
+ # Kill Unicorns in multiple ways O_O
98
+ #
99
+ def kill_unicorn(signal)
100
+ if unicorn_is_running?
101
+ puts 'Stopping unicorn...'
102
+ unicorn_send_signal(signal)
103
+ else
104
+ puts 'Unicorn is not running'
105
+ end
106
+ end
107
+
108
+ # Start the Unicorn server
109
+ #
110
+ def start_unicorn
111
+ if test("[ -e #{fetch(:unicorn_config_file_path)} ]")
112
+ unicorn_config_file_path = fetch(:unicorn_config_file_path)
113
+ elsif test("[ -e #{fetch(:unicorn_config_stage_file_path)} ]")
114
+ unicorn_config_file_path = fetch(:unicorn_config_stage_file_path)
115
+ else
116
+ fail "Config file for \"#{fetch(:unicorn_env)}\" environment was not found at either \"#{fetch(:unicorn_config_file_path)}\" or \"#{fetch(:unicorn_config_stage_file_path)}\""
117
+ end
118
+
119
+ if test("[ -e #{fetch(:unicorn_pid)} ]")
120
+ if unicorn_is_running?
121
+ puts 'Unicorn is already running!'
122
+ return
123
+ else
124
+ unicorn_execute :rm, fetch(:unicorn_pid)
125
+ end
126
+ end
127
+
128
+ puts 'Starting unicorn...'
129
+
130
+ within fetch(:app_path) do
131
+ with rails_env: fetch(:rails_env), bundle_gemfile: fetch(:bundle_gemfile) do
132
+ unicorn_execute fetch(:unicorn_bin), '-c', unicorn_config_file_path, '-E', fetch(:unicorn_rack_env), '-D', fetch(:unicorn_options)
133
+ end
134
+ end
135
+ end
136
+
137
+ def duplicate_unicorn
138
+ if unicorn_is_running?
139
+ unicorn_send_signal('USR2')
140
+ else
141
+ start_unicorn
142
+ end
143
+ end
144
+
145
+ def unicorn_roles
146
+ fetch(:unicorn_roles, :app)
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,5 @@
1
+ module CapistranoUnicorn
2
+ unless defined?(::CapistranoUnicorn::VERSION)
3
+ VERSION = "0.3.1".freeze
4
+ end
5
+ 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
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'capistrano-spec'
2
+ require 'capistrano-unicorn'
3
+
4
+ RSpec.configure do |config|
5
+ config.include Capistrano::Spec::Matchers
6
+ config.include Capistrano::Spec::Helpers
7
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-unicorn-sic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Sebastian Gassner, Dan Sosedoff, Florian Schwab
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: unicorn
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: capistrano
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.0.0
55
+ description: Capistrano 3.x plugin that integrates Unicorn server tasks.
56
+ email: sebastian.gassner@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".gitignore"
62
+ - ".rspec"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - LICENSE
66
+ - NEWS.md
67
+ - README.md
68
+ - Rakefile
69
+ - capistrano-unicorn.gemspec
70
+ - examples/rails3.rb
71
+ - lib/capistrano-unicorn.rb
72
+ - lib/capistrano/tasks/unicorn.cap
73
+ - lib/capistrano/unicorn.rb
74
+ - lib/capistrano/unicorn/utility.rb
75
+ - lib/capistrano/unicorn/version.rb
76
+ - lib/unicorn.rb
77
+ - spec/capistrano_integration_spec.rb
78
+ - spec/config_spec.rb
79
+ - spec/spec_helper.rb
80
+ homepage: https://github.com/SICSoftwareGmbH/capistrano-unicorn
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.2.2
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Unicorn integration for Capistrano 3.x
104
+ test_files:
105
+ - spec/capistrano_integration_spec.rb
106
+ - spec/config_spec.rb
107
+ - spec/spec_helper.rb