capistrano 2.6.1.pre → 2.7.0
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.
- data/CHANGELOG +2 -2
- data/Gemfile +9 -1
- data/README.mdown +21 -10
- data/lib/capistrano/cli/help.txt +1 -1
- data/lib/capistrano/cli/options.rb +4 -4
- data/lib/capistrano/cli/ui.rb +2 -2
- data/lib/capistrano/configuration/actions/invocation.rb +3 -0
- data/lib/capistrano/configuration/connections.rb +5 -2
- data/lib/capistrano/recipes/deploy.rb +10 -40
- data/lib/capistrano/recipes/deploy/scm/git.rb +10 -2
- data/lib/capistrano/task_definition.rb +6 -6
- data/lib/capistrano/version.rb +3 -3
- data/test/cli/options_test.rb +1 -1
- data/test/command_test.rb +9 -6
- data/test/configuration/connections_test.rb +46 -22
- data/test/configuration/loading_test.rb +7 -7
- data/test/recipes_test.rb +25 -0
- data/test/utils.rb +4 -6
- metadata +71 -114
- data/VERSION +0 -1
data/CHANGELOG
CHANGED
@@ -14,8 +14,8 @@ implemented simply as `self.gsub(/\s+/, ' ')`.
|
|
14
14
|
Here's the run-down of changes, and their committers, as always - a huge thank
|
15
15
|
you to the community that continues to drive Capistrano's development.
|
16
16
|
|
17
|
-
* `deploy:setup` now respects `:group_writable` (
|
18
|
-
* Fixes to `:scm_verbose` for the Git module (defaults to On.) (
|
17
|
+
* `deploy:setup` now respects `:group_writable` (Daniel Duvall)
|
18
|
+
* Fixes to `:scm_verbose` for the Git module (defaults to On.) (Matthew Davies)
|
19
19
|
* Will now copy hidden files in the project's root into the release
|
20
20
|
directory (Mark Jaquith)
|
21
21
|
* Now handles closing already-dead connections in a sane way (does not raise
|
data/Gemfile
CHANGED
@@ -3,4 +3,12 @@ source "http://rubygems.org"
|
|
3
3
|
# Specify your gem's dependencies in capistrano.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
6
|
+
#
|
7
|
+
# Development Dependencies from the Gemfile
|
8
|
+
# are merged here.
|
9
|
+
#
|
10
|
+
group :development do
|
11
|
+
gem 'rake'
|
12
|
+
gem 'ruby-debug', :platform => :mri_18
|
13
|
+
gem 'ruby-debug19', :platform => :mri_19
|
14
|
+
end
|
data/README.mdown
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
## Capistrano
|
2
2
|
|
3
|
-
Capistrano is a utility and framework for executing commands in parallel on
|
3
|
+
Capistrano is a utility and framework for executing commands in parallel on
|
4
|
+
multiple remote machines, via SSH. It uses a simple DSL (borrowed in part from
|
5
|
+
[Rake](http://rake.rubyforge.org/)) that allows you to define _tasks_, which may
|
6
|
+
be applied to machines in certain roles. It also supports tunneling connections
|
7
|
+
via some gateway machine to allow operations to be performed behind VPN's and
|
8
|
+
firewalls.
|
4
9
|
|
5
|
-
Capistrano was originally designed to simplify and automate deployment of web
|
10
|
+
Capistrano was originally designed to simplify and automate deployment of web
|
11
|
+
applications to distributed environments, and originally came bundled with a set
|
12
|
+
of tasks designed for deploying Rails applications.
|
6
13
|
|
7
14
|
## Documentation
|
8
15
|
|
@@ -16,17 +23,18 @@ Capistrano was originally designed to simplify and automate deployment of web ap
|
|
16
23
|
* [Net::SSH::Gateway](http://net-ssh.rubyforge.org)
|
17
24
|
* [HighLine](http://highline.rubyforge.org)
|
18
25
|
|
19
|
-
If you want to run the tests, you'll also need to
|
20
|
-
|
21
|
-
* [Echoe](https://github.com/fauna/echoe)
|
22
|
-
* [Mocha](http://mocha.rubyforge.org)
|
26
|
+
If you want to run the tests, you'll also need to install the dependencies with
|
27
|
+
Bundler, see the `Gemfile` within .
|
23
28
|
|
24
29
|
## ASSUMPTIONS
|
25
30
|
|
26
|
-
Capistrano is "opinionated software", which means it has very firm ideas about
|
31
|
+
Capistrano is "opinionated software", which means it has very firm ideas about
|
32
|
+
how things ought to be done, and tries to force those ideas on you. Some of the
|
33
|
+
assumptions behind these opinions are:
|
27
34
|
|
28
35
|
* You are using SSH to access the remote servers.
|
29
|
-
* You either have the same password to all target machines, or you have public
|
36
|
+
* You either have the same password to all target machines, or you have public
|
37
|
+
keys in place to allow passwordless access to them.
|
30
38
|
|
31
39
|
Do not expect these assumptions to change.
|
32
40
|
|
@@ -39,9 +47,12 @@ In general, you'll use Capistrano as follows:
|
|
39
47
|
|
40
48
|
Use the `cap` script as follows:
|
41
49
|
|
42
|
-
|
50
|
+
cap sometask
|
43
51
|
|
44
|
-
By default, the script will look for a file called one of `capfile` or
|
52
|
+
By default, the script will look for a file called one of `capfile` or
|
53
|
+
`Capfile`. The `someaction` text indicates which task to execute. You can do
|
54
|
+
"cap -h" to see all the available options and "cap -T" to see all the available
|
55
|
+
tasks.
|
45
56
|
|
46
57
|
## LICENSE:
|
47
58
|
|
data/lib/capistrano/cli/help.txt
CHANGED
@@ -33,7 +33,7 @@ The following options are understood:
|
|
33
33
|
|
34
34
|
<%= color '-n, --dry-run', :bold %>
|
35
35
|
Causes Capistrano to simply display each remote command, without executing it. In this sense it is similar to --debug, but without the prompt. Note that commands executed locally are still run--only remote commands are skipped.
|
36
|
-
|
36
|
+
|
37
37
|
<%= color '-p, --password', :bold %>
|
38
38
|
Normally, cap will prompt for the password on-demand, the first time it is needed. This can make it hard to walk away from Capistrano, since you might not know if it will prompt for a password down the road. In such cases, you can use the -p option to force cap to prompt for the password immediately.
|
39
39
|
|
@@ -54,9 +54,9 @@ module Capistrano
|
|
54
54
|
exit
|
55
55
|
end
|
56
56
|
|
57
|
-
opts.on("-l", "--logger [STDERR|STDOUT|file]",
|
57
|
+
opts.on("-l", "--logger [STDERR|STDOUT|file]",
|
58
58
|
"Choose logger method. STDERR used by default."
|
59
|
-
) do |value|
|
59
|
+
) do |value|
|
60
60
|
options[:output] = if value.nil? || value.upcase == 'STDERR'
|
61
61
|
# Using default logger.
|
62
62
|
nil
|
@@ -201,7 +201,7 @@ module Capistrano
|
|
201
201
|
def default_sysconf #:nodoc:
|
202
202
|
File.join(sysconf_directory, "capistrano.conf")
|
203
203
|
end
|
204
|
-
|
204
|
+
|
205
205
|
def default_dotfile #:nodoc:
|
206
206
|
File.join(home_directory, ".caprc")
|
207
207
|
end
|
@@ -211,7 +211,7 @@ module Capistrano
|
|
211
211
|
# appropriate location for this file in Windows.
|
212
212
|
ENV["SystemRoot"] || '/etc'
|
213
213
|
end
|
214
|
-
|
214
|
+
|
215
215
|
def home_directory #:nodoc:
|
216
216
|
ENV["HOME"] ||
|
217
217
|
(ENV["HOMEPATH"] && "#{ENV["HOMEDRIVE"]}#{ENV["HOMEPATH"]}") ||
|
data/lib/capistrano/cli/ui.rb
CHANGED
@@ -22,7 +22,7 @@ module Capistrano
|
|
22
22
|
def password_prompt(prompt="Password: ")
|
23
23
|
ui.ask(prompt) { |q| q.echo = false }
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Debug mode prompt
|
27
27
|
def debug_prompt(cmd)
|
28
28
|
ui.say("Preparing to execute command: #{cmd}")
|
@@ -37,4 +37,4 @@ module Capistrano
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
|
-
end
|
40
|
+
end
|
@@ -111,6 +111,9 @@ module Capistrano
|
|
111
111
|
# * :except - specifies a condition limiting which hosts will be selected to
|
112
112
|
# run the command. This is the inverse of :only (hosts that do _not_ match
|
113
113
|
# the condition will be selected).
|
114
|
+
# * :on_no_matching_servers - if :continue, will continue to execute tasks if
|
115
|
+
# no matching servers are found for the host criteria. The default is to raise
|
116
|
+
# a NoMatchingServersError exception.
|
114
117
|
# * :once - if true, only the first matching server will be selected. The default
|
115
118
|
# is false (all matching servers will be selected).
|
116
119
|
# * :max_hosts - specifies the maximum number of hosts that should be selected
|
@@ -156,7 +156,7 @@ module Capistrano
|
|
156
156
|
servers = find_servers_for_task(task, options)
|
157
157
|
|
158
158
|
if servers.empty?
|
159
|
-
if ENV['HOSTFILTER']
|
159
|
+
if ENV['HOSTFILTER'] || task.options.merge(options)[:on_no_matching_servers] == :continue
|
160
160
|
logger.info "skipping `#{task.fully_qualified_name}' because no servers matched"
|
161
161
|
return
|
162
162
|
else
|
@@ -170,7 +170,10 @@ module Capistrano
|
|
170
170
|
end
|
171
171
|
else
|
172
172
|
servers = find_servers(options)
|
173
|
-
|
173
|
+
if servers.empty?
|
174
|
+
raise Capistrano::NoMatchingServersError, "no servers found to match #{options.inspect}" if options[:on_no_matching_servers] != :continue
|
175
|
+
return
|
176
|
+
end
|
174
177
|
end
|
175
178
|
|
176
179
|
servers = [servers.first] if options[:once]
|
@@ -56,7 +56,7 @@ _cset(:current_path) { File.join(deploy_to, current_dir) }
|
|
56
56
|
_cset(:release_path) { File.join(releases_path, release_name) }
|
57
57
|
|
58
58
|
_cset(:releases) { capture("ls -x #{releases_path}", :except => { :no_release => true }).split.sort }
|
59
|
-
_cset(:current_release) { File.join(releases_path, releases.last) }
|
59
|
+
_cset(:current_release) { releases.length > 0 ? File.join(releases_path, releases.last) : nil }
|
60
60
|
_cset(:previous_release) { releases.length > 1 ? File.join(releases_path, releases[-2]) : nil }
|
61
61
|
|
62
62
|
_cset(:current_revision) { capture("cat #{current_path}/REVISION", :except => { :no_release => true }).chomp }
|
@@ -304,23 +304,11 @@ namespace :deploy do
|
|
304
304
|
end
|
305
305
|
|
306
306
|
desc <<-DESC
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
If you are deploying a Rails 2.3.x application, you will need to install
|
311
|
-
these http://github.com/rails/irs_process_scripts (more info about why
|
312
|
-
on that page.)
|
313
|
-
|
314
|
-
By default, this will be invoked via sudo as the `app' user. If \
|
315
|
-
you wish to run it as a different user, set the :runner variable to \
|
316
|
-
that user. If you are in an environment where you can't use sudo, set \
|
317
|
-
the :use_sudo variable to false:
|
318
|
-
|
319
|
-
set :use_sudo, false
|
307
|
+
Blank task exists as a hook into which to install your own environment \
|
308
|
+
specific behaviour.
|
320
309
|
DESC
|
321
310
|
task :restart, :roles => :app, :except => { :no_release => true } do
|
322
|
-
|
323
|
-
try_runner "#{current_path}/script/process/reaper"
|
311
|
+
# Empty Task to overload with your platform specifics
|
324
312
|
end
|
325
313
|
|
326
314
|
namespace :rollback do
|
@@ -488,37 +476,19 @@ namespace :deploy do
|
|
488
476
|
end
|
489
477
|
|
490
478
|
desc <<-DESC
|
491
|
-
|
492
|
-
|
493
|
-
your application listeners. For Rails applications, you might just have \
|
494
|
-
that script invoke `script/process/spawner' with the appropriate \
|
495
|
-
arguments.
|
496
|
-
|
497
|
-
By default, the script will be executed via sudo as the `app' user. If \
|
498
|
-
you wish to run it as a different user, set the :runner variable to \
|
499
|
-
that user. If you are in an environment where you can't use sudo, set \
|
500
|
-
the :use_sudo variable to false.
|
479
|
+
Blank task exists as a hook into which to install your own environment \
|
480
|
+
specific behaviour.
|
501
481
|
DESC
|
502
482
|
task :start, :roles => :app do
|
503
|
-
|
504
|
-
run "cd #{current_path} && #{try_runner} nohup script/spin"
|
483
|
+
# Empty Task to overload with your platform specifics
|
505
484
|
end
|
506
485
|
|
507
486
|
desc <<-DESC
|
508
|
-
|
509
|
-
|
510
|
-
spawned. As such, it is fairly Rails specific and may need to be \
|
511
|
-
overridden for other systems.
|
512
|
-
|
513
|
-
By default, the script will be executed via sudo as the `app' user. If \
|
514
|
-
you wish to run it as a different user, set the :runner variable to \
|
515
|
-
that user. If you are in an environment where you can't use sudo, set \
|
516
|
-
the :use_sudo variable to false.
|
487
|
+
Blank task exists as a hook into which to install your own environment \
|
488
|
+
specific behaviour.
|
517
489
|
DESC
|
518
490
|
task :stop, :roles => :app do
|
519
|
-
|
520
|
-
run "if [ -f #{current_path}/tmp/pids/dispatch.spawner.pid ]; then #{try_runner} #{current_path}/script/process/reaper -a kill -r dispatch.spawner.pid; fi"
|
521
|
-
try_runner "#{current_path}/script/process/reaper -a kill"
|
491
|
+
# Empty Task to overload with your platform specifics
|
522
492
|
end
|
523
493
|
|
524
494
|
namespace :pending do
|
@@ -148,7 +148,11 @@ module Capistrano
|
|
148
148
|
if variable(:git_enable_submodules)
|
149
149
|
execute << "#{git} submodule #{verbose} init"
|
150
150
|
execute << "#{git} submodule #{verbose} sync"
|
151
|
-
|
151
|
+
if false == variable(:git_submodules_recursive)
|
152
|
+
execute << "#{git} submodule #{verbose} update --init"
|
153
|
+
else
|
154
|
+
execute << "#{git} submodule #{verbose} update --init --recursive"
|
155
|
+
end
|
152
156
|
end
|
153
157
|
|
154
158
|
execute.join(" && ").compact
|
@@ -187,7 +191,11 @@ module Capistrano
|
|
187
191
|
execute << "#{git} submodule #{verbose} init"
|
188
192
|
execute << "for mod in `#{git} submodule status | awk '{ print $2 }'`; do #{git} config -f .git/config submodule.${mod}.url `#{git} config -f .gitmodules --get submodule.${mod}.url` && echo Synced $mod; done"
|
189
193
|
execute << "#{git} submodule #{verbose} sync"
|
190
|
-
|
194
|
+
if false == variable(:git_submodules_recursive)
|
195
|
+
execute << "#{git} submodule #{verbose} update --init"
|
196
|
+
else
|
197
|
+
execute << "#{git} submodule #{verbose} update --init --recursive"
|
198
|
+
end
|
191
199
|
end
|
192
200
|
|
193
201
|
# Make sure there's nothing else lying around in the repository (for
|
@@ -4,13 +4,13 @@ module Capistrano
|
|
4
4
|
# Represents the definition of a single task.
|
5
5
|
class TaskDefinition
|
6
6
|
attr_reader :name, :namespace, :options, :body, :desc, :on_error, :max_hosts
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(name, namespace, options={}, &block)
|
9
|
-
|
9
|
+
|
10
10
|
if name.to_s =~ /^(?:before_|after_)/
|
11
11
|
Kernel.warn("[Deprecation Warning] Naming tasks with before_ and after_ is deprecated, please see the new before() and after() methods. (Offending task name was #{name})")
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
@name, @namespace, @options = name, namespace, options
|
15
15
|
@desc = @options.delete(:desc)
|
16
16
|
@on_error = options.delete(:on_error)
|
@@ -18,7 +18,7 @@ module Capistrano
|
|
18
18
|
@body = block or raise ArgumentError, "a task requires a block"
|
19
19
|
@servers = nil
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
# Returns the task's fully-qualified name, including the namespace
|
23
23
|
def fully_qualified_name
|
24
24
|
@fully_qualified_name ||= begin
|
@@ -29,7 +29,7 @@ module Capistrano
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# Returns the description for this task, with newlines collapsed and
|
34
34
|
# whitespace stripped. Returns the empty string if there is no
|
35
35
|
# description for this task.
|
@@ -37,7 +37,7 @@ module Capistrano
|
|
37
37
|
@description = nil if rebuild
|
38
38
|
@description ||= begin
|
39
39
|
description = @desc || ""
|
40
|
-
|
40
|
+
|
41
41
|
indentation = description[/\A\s+/]
|
42
42
|
if indentation
|
43
43
|
reformatted_description = ""
|
data/lib/capistrano/version.rb
CHANGED
data/test/cli/options_test.rb
CHANGED
@@ -198,7 +198,7 @@ class CLIOptionsTest < Test::Unit::TestCase
|
|
198
198
|
|
199
199
|
def test_parse_options_with_V_should_show_version_and_exit
|
200
200
|
@cli.args << "-V"
|
201
|
-
@cli.expects(:puts).with { |s| s.include?(Capistrano::Version
|
201
|
+
@cli.expects(:puts).with { |s| s.include?(Capistrano::Version.to_s) }
|
202
202
|
@cli.expects(:exit).raises(ExitException)
|
203
203
|
assert_raises(ExitException) { @cli.parse_options! }
|
204
204
|
end
|
data/test/command_test.rb
CHANGED
@@ -214,7 +214,9 @@ class CommandTest < Test::Unit::TestCase
|
|
214
214
|
mock_session(new_channel[10]),
|
215
215
|
mock_session(new_channel[7])]
|
216
216
|
cmd = Capistrano::Command.new("ls", sessions)
|
217
|
-
assert_nothing_raised
|
217
|
+
assert_nothing_raised do
|
218
|
+
cmd.process!
|
219
|
+
end
|
218
220
|
end
|
219
221
|
|
220
222
|
def test_process_should_instantiate_command_and_process!
|
@@ -240,11 +242,12 @@ class CommandTest < Test::Unit::TestCase
|
|
240
242
|
private
|
241
243
|
|
242
244
|
def mock_session(channel=nil)
|
243
|
-
stub('session',
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
245
|
+
stub('session',
|
246
|
+
:open_channel => channel,
|
247
|
+
:preprocess => true,
|
248
|
+
:postprocess => true,
|
249
|
+
:listeners => {},
|
250
|
+
:xserver => server("capistrano"))
|
248
251
|
end
|
249
252
|
|
250
253
|
class MockChannel < Hash
|
@@ -71,7 +71,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
71
71
|
Net::SSH::Gateway.expects(:new).with("gateway", "user", :debug => :verbose, :port => 8080, :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
|
72
72
|
assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
def test_connection_factory_as_gateway_should_chain_gateways_if_gateway_variable_is_an_array
|
76
76
|
@config.values[:gateway] = ["j@gateway1", "k@gateway2"]
|
77
77
|
gateway1 = mock
|
@@ -80,7 +80,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
80
80
|
Net::SSH::Gateway.expects(:new).with("127.0.0.1", "k", :port => 65535, :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
|
81
81
|
assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def test_connection_factory_as_gateway_should_chain_gateways_if_gateway_variable_is_a_hash
|
85
85
|
@config.values[:gateway] = { ["j@gateway1", "k@gateway2"] => :default }
|
86
86
|
gateway1 = mock
|
@@ -89,7 +89,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
89
89
|
Net::SSH::Gateway.expects(:new).with("127.0.0.1", "k", :port => 65535, :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
|
90
90
|
assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
def test_connection_factory_as_gateway_should_share_gateway_between_connections
|
94
94
|
@config.values[:gateway] = "j@gateway"
|
95
95
|
Net::SSH::Gateway.expects(:new).once.with("gateway", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
|
@@ -98,7 +98,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
98
98
|
@config.establish_connections_to(server("capistrano"))
|
99
99
|
@config.establish_connections_to(server("another"))
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
def test_connection_factory_as_gateway_should_share_gateway_between_like_connections_if_gateway_variable_is_a_hash
|
103
103
|
@config.values[:gateway] = { "j@gateway" => [ "capistrano", "another"] }
|
104
104
|
Net::SSH::Gateway.expects(:new).once.with("gateway", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
|
@@ -107,7 +107,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
107
107
|
@config.establish_connections_to(server("capistrano"))
|
108
108
|
@config.establish_connections_to(server("another"))
|
109
109
|
end
|
110
|
-
|
110
|
+
|
111
111
|
def test_connection_factory_as_gateways_should_not_share_gateway_between_unlike_connections_if_gateway_variable_is_a_hash
|
112
112
|
@config.values[:gateway] = { "j@gateway" => [ "capistrano", "another"], "k@gateway2" => "yafhost" }
|
113
113
|
Net::SSH::Gateway.expects(:new).once.with("gateway", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
|
@@ -123,23 +123,23 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
123
123
|
Capistrano::SSH.expects(:connect).with { |s,| s.host == "capistrano" }.returns(:success)
|
124
124
|
assert @config.sessions.empty?
|
125
125
|
@config.establish_connections_to(server("capistrano"))
|
126
|
-
|
126
|
+
assert_equal ["capistrano"], @config.sessions.keys.map(&:host)
|
127
127
|
end
|
128
128
|
|
129
129
|
def test_establish_connections_to_should_accept_an_array
|
130
130
|
Capistrano::SSH.expects(:connect).times(3).returns(:success)
|
131
131
|
assert @config.sessions.empty?
|
132
132
|
@config.establish_connections_to(%w(cap1 cap2 cap3).map { |s| server(s) })
|
133
|
-
|
133
|
+
assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map(&:host)
|
134
134
|
end
|
135
135
|
|
136
136
|
def test_establish_connections_to_should_not_attempt_to_reestablish_existing_connections
|
137
137
|
Capistrano::SSH.expects(:connect).times(2).returns(:success)
|
138
138
|
@config.sessions[server("cap1")] = :ok
|
139
139
|
@config.establish_connections_to(%w(cap1 cap2 cap3).map { |s| server(s) })
|
140
|
-
|
140
|
+
assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map(&:host)
|
141
141
|
end
|
142
|
-
|
142
|
+
|
143
143
|
def test_establish_connections_to_should_raise_one_connection_error_on_failure
|
144
144
|
Capistrano::SSH.expects(:connect).times(2).raises(Exception)
|
145
145
|
assert_raises(Capistrano::ConnectionError) {
|
@@ -149,7 +149,6 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
149
149
|
|
150
150
|
def test_connection_error_should_include_accessor_with_host_array
|
151
151
|
Capistrano::SSH.expects(:connect).times(2).raises(Exception)
|
152
|
-
|
153
152
|
begin
|
154
153
|
@config.establish_connections_to(%w(cap1 cap2).map { |s| server(s) })
|
155
154
|
flunk "expected an exception to be raised"
|
@@ -158,7 +157,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
158
157
|
assert_equal %w(cap1 cap2), e.hosts.map { |h| h.to_s }.sort
|
159
158
|
end
|
160
159
|
end
|
161
|
-
|
160
|
+
|
162
161
|
def test_connection_error_should_only_include_failed_hosts
|
163
162
|
Capistrano::SSH.expects(:connect).with(server('cap1'), anything).raises(Exception)
|
164
163
|
Capistrano::SSH.expects(:connect).with(server('cap2'), anything).returns(:success)
|
@@ -189,6 +188,11 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
189
188
|
assert_raises(Capistrano::NoMatchingServersError) { @config.execute_on_servers(:a => :b, :c => :d) { |list| } }
|
190
189
|
end
|
191
190
|
|
191
|
+
def test_execute_on_servers_without_current_task_should_not_raise_error_if_no_matching_servers_and_continue_on_no_matching_servers
|
192
|
+
@config.expects(:find_servers).with(:a => :b, :c => :d, :on_no_matching_servers => :continue).returns([])
|
193
|
+
assert_nothing_raised { @config.execute_on_servers(:a => :b, :c => :d, :on_no_matching_servers => :continue) { |list| } }
|
194
|
+
end
|
195
|
+
|
192
196
|
def test_execute_on_servers_should_raise_an_error_if_the_current_task_has_no_matching_servers_by_default
|
193
197
|
@config.current_task = mock_task
|
194
198
|
@config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([])
|
@@ -198,7 +202,27 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
198
202
|
end
|
199
203
|
end
|
200
204
|
end
|
201
|
-
|
205
|
+
|
206
|
+
def test_execute_on_servers_should_not_raise_an_error_if_the_current_task_has_no_matching_servers_by_default_and_continue_on_no_matching_servers
|
207
|
+
@config.current_task = mock_task(:on_no_matching_servers => :continue)
|
208
|
+
@config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([])
|
209
|
+
assert_nothing_raised do
|
210
|
+
@config.execute_on_servers do
|
211
|
+
flunk "should not get here"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_execute_on_servers_should_not_raise_an_error_if_the_current_task_has_no_matching_servers_by_default_and_command_continues_on_no_matching_servers
|
217
|
+
@config.current_task = mock_task
|
218
|
+
@config.expects(:find_servers_for_task).with(@config.current_task, :on_no_matching_servers => :continue).returns([])
|
219
|
+
assert_nothing_raised do
|
220
|
+
@config.execute_on_servers(:on_no_matching_servers => :continue) do
|
221
|
+
flunk "should not get here"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
202
226
|
def test_execute_on_servers_should_determine_server_list_from_active_task
|
203
227
|
assert @config.sessions.empty?
|
204
228
|
@config.current_task = mock_task
|
@@ -237,7 +261,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
237
261
|
assert block_called
|
238
262
|
assert_equal %w(cap1), @config.sessions.keys.sort.map { |s| s.host }
|
239
263
|
end
|
240
|
-
|
264
|
+
|
241
265
|
def test_execute_servers_should_raise_connection_error_on_failure_by_default
|
242
266
|
@config.current_task = mock_task
|
243
267
|
@config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1")])
|
@@ -248,7 +272,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
248
272
|
end
|
249
273
|
end
|
250
274
|
end
|
251
|
-
|
275
|
+
|
252
276
|
def test_execute_servers_should_not_raise_connection_error_on_failure_with_on_errors_continue
|
253
277
|
@config.current_task = mock_task(:on_error => :continue)
|
254
278
|
@config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2")])
|
@@ -260,7 +284,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
260
284
|
end
|
261
285
|
}
|
262
286
|
end
|
263
|
-
|
287
|
+
|
264
288
|
def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_connection_errors_with_on_errors_continue
|
265
289
|
list = [server("cap1"), server("cap2")]
|
266
290
|
@config.current_task = mock_task(:on_error => :continue)
|
@@ -275,7 +299,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
275
299
|
assert_equal %w(cap2), servers.map { |s| s.host }
|
276
300
|
end
|
277
301
|
end
|
278
|
-
|
302
|
+
|
279
303
|
def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_command_errors_with_on_errors_continue
|
280
304
|
cap1 = server("cap1")
|
281
305
|
cap2 = server("cap2")
|
@@ -292,7 +316,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
292
316
|
assert_equal %w(cap2), servers.map { |s| s.host }
|
293
317
|
end
|
294
318
|
end
|
295
|
-
|
319
|
+
|
296
320
|
def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_transfer_errors_with_on_errors_continue
|
297
321
|
cap1 = server("cap1")
|
298
322
|
cap2 = server("cap2")
|
@@ -309,7 +333,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
309
333
|
assert_equal %w(cap2), servers.map { |s| s.host }
|
310
334
|
end
|
311
335
|
end
|
312
|
-
|
336
|
+
|
313
337
|
def test_connect_should_establish_connections_to_all_servers_in_scope
|
314
338
|
assert @config.sessions.empty?
|
315
339
|
@config.current_task = mock_task
|
@@ -318,7 +342,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
318
342
|
@config.connect!
|
319
343
|
assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map { |s| s.host }
|
320
344
|
end
|
321
|
-
|
345
|
+
|
322
346
|
def test_execute_on_servers_should_only_run_on_tasks_max_hosts_hosts_at_once
|
323
347
|
cap1 = server("cap1")
|
324
348
|
cap2 = server("cap2")
|
@@ -336,7 +360,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
336
360
|
end
|
337
361
|
assert_equal 2, block_called
|
338
362
|
end
|
339
|
-
|
363
|
+
|
340
364
|
def test_execute_on_servers_should_only_run_on_max_hosts_hosts_at_once
|
341
365
|
cap1 = server("cap1")
|
342
366
|
cap2 = server("cap2")
|
@@ -354,7 +378,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
354
378
|
end
|
355
379
|
assert_equal 2, block_called
|
356
380
|
end
|
357
|
-
|
381
|
+
|
358
382
|
def test_execute_on_servers_should_cope_with_already_dropped_connections_when_attempting_to_close_them
|
359
383
|
cap1 = server("cap1")
|
360
384
|
cap2 = server("cap2")
|
@@ -372,7 +396,7 @@ class ConfigurationConnectionsTest < Test::Unit::TestCase
|
|
372
396
|
@config.execute_on_servers {}
|
373
397
|
@config.execute_on_servers {}
|
374
398
|
end
|
375
|
-
|
399
|
+
|
376
400
|
def test_connect_should_honor_once_option
|
377
401
|
assert @config.sessions.empty?
|
378
402
|
@config.current_task = mock_task
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'utils'
|
2
2
|
require 'capistrano/configuration/loading'
|
3
3
|
|
4
4
|
class ConfigurationLoadingTest < Test::Unit::TestCase
|
@@ -106,7 +106,7 @@ class ConfigurationLoadingTest < Test::Unit::TestCase
|
|
106
106
|
|
107
107
|
def test_require_from_config_should_load_file_in_config_scope
|
108
108
|
assert_nothing_raised do
|
109
|
-
@config.require "#{File.dirname(__FILE__)}/../fixtures/custom"
|
109
|
+
@config.require "#{File.expand_path(File.dirname(__FILE__))}/../fixtures/custom"
|
110
110
|
end
|
111
111
|
assert_equal :custom, @config.ping
|
112
112
|
end
|
@@ -118,14 +118,14 @@ class ConfigurationLoadingTest < Test::Unit::TestCase
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def test_require_from_config_should_return_false_when_called_a_second_time_with_same_args
|
121
|
-
assert @config.require("#{File.dirname(__FILE__)}/../fixtures/custom")
|
122
|
-
assert_equal false, @config.require("#{File.dirname(__FILE__)}/../fixtures/custom")
|
121
|
+
assert @config.require("#{File.expand_path(File.dirname(__FILE__))}/../fixtures/custom")
|
122
|
+
assert_equal false, @config.require("#{File.expand_path(File.dirname(__FILE__))}/../fixtures/custom")
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
def test_require_in_multiple_instances_should_load_recipes_in_each_instance
|
126
126
|
config2 = MockConfig.new
|
127
|
-
@config.require "#{File.dirname(__FILE__)}/../fixtures/custom"
|
128
|
-
config2.require "#{File.dirname(__FILE__)}/../fixtures/custom"
|
127
|
+
@config.require "#{File.expand_path(File.dirname(__FILE__))}/../fixtures/custom"
|
128
|
+
config2.require "#{File.expand_path(File.dirname(__FILE__))}/../fixtures/custom"
|
129
129
|
assert_equal :custom, @config.ping
|
130
130
|
assert_equal :custom, config2.ping
|
131
131
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'utils'
|
2
|
+
require 'capistrano/configuration'
|
3
|
+
|
4
|
+
class RecipesTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@config = Capistrano::Configuration.new
|
8
|
+
@config.stubs(:logger).returns(stub_everything)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_current_releases_does_not_cause_error_on_dry_run
|
12
|
+
@config.dry_run = true
|
13
|
+
@config.load 'deploy'
|
14
|
+
@config.load do
|
15
|
+
set :application, "foo"
|
16
|
+
task :dry_run_test do
|
17
|
+
fetch :current_release
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
assert_nothing_raised do
|
22
|
+
@config.dry_run_test
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/test/utils.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'redgreen' unless ENV['TM_FILENAME']
|
4
|
-
gem 'mocha'
|
5
|
-
rescue LoadError
|
6
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
7
3
|
|
4
|
+
require 'ruby-debug'
|
8
5
|
require 'test/unit'
|
9
6
|
require 'mocha'
|
7
|
+
|
10
8
|
require 'capistrano/server_definition'
|
11
9
|
|
12
10
|
module TestExtensions
|
metadata
CHANGED
@@ -1,136 +1,102 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 2
|
8
|
-
- 6
|
9
|
-
- 1
|
10
|
-
- pre
|
11
|
-
version: 2.6.1.pre
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.7.0
|
5
|
+
prerelease:
|
12
6
|
platform: ruby
|
13
|
-
authors:
|
7
|
+
authors:
|
14
8
|
- Jamis Buck
|
15
9
|
- Lee Hambley
|
16
10
|
autorequire:
|
17
11
|
bindir: bin
|
18
12
|
cert_chain: []
|
19
|
-
|
20
|
-
date: 2011-03-22 00:00:00 +01:00
|
13
|
+
date: 2011-03-22 00:00:00.000000000 +01:00
|
21
14
|
default_executable:
|
22
|
-
dependencies:
|
23
|
-
- !ruby/object:Gem::Dependency
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
24
17
|
name: highline
|
25
|
-
|
26
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
requirement: &2157549420 !ruby/object:Gem::Requirement
|
27
19
|
none: false
|
28
|
-
requirements:
|
29
|
-
- -
|
30
|
-
- !ruby/object:Gem::Version
|
31
|
-
|
32
|
-
segments:
|
33
|
-
- 0
|
34
|
-
version: "0"
|
20
|
+
requirements:
|
21
|
+
- - ! '>='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '0'
|
35
24
|
type: :runtime
|
36
|
-
version_requirements: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: net-ssh
|
39
25
|
prerelease: false
|
40
|
-
|
26
|
+
version_requirements: *2157549420
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: net-ssh
|
29
|
+
requirement: &2157642760 !ruby/object:Gem::Requirement
|
41
30
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
hash: 19
|
46
|
-
segments:
|
47
|
-
- 2
|
48
|
-
- 0
|
49
|
-
- 14
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
50
34
|
version: 2.0.14
|
51
35
|
type: :runtime
|
52
|
-
version_requirements: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: net-sftp
|
55
36
|
prerelease: false
|
56
|
-
|
37
|
+
version_requirements: *2157642760
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: net-sftp
|
40
|
+
requirement: &2157664760 !ruby/object:Gem::Requirement
|
57
41
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
hash: 15
|
62
|
-
segments:
|
63
|
-
- 2
|
64
|
-
- 0
|
65
|
-
- 0
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
66
45
|
version: 2.0.0
|
67
46
|
type: :runtime
|
68
|
-
version_requirements: *id003
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: net-scp
|
71
47
|
prerelease: false
|
72
|
-
|
48
|
+
version_requirements: *2157664760
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: net-scp
|
51
|
+
requirement: &2157664160 !ruby/object:Gem::Requirement
|
73
52
|
none: false
|
74
|
-
requirements:
|
75
|
-
- -
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
hash: 23
|
78
|
-
segments:
|
79
|
-
- 1
|
80
|
-
- 0
|
81
|
-
- 0
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
82
56
|
version: 1.0.0
|
83
57
|
type: :runtime
|
84
|
-
version_requirements: *id004
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: net-ssh-gateway
|
87
58
|
prerelease: false
|
88
|
-
|
59
|
+
version_requirements: *2157664160
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: net-ssh-gateway
|
62
|
+
requirement: &2157663580 !ruby/object:Gem::Requirement
|
89
63
|
none: false
|
90
|
-
requirements:
|
91
|
-
- -
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
hash: 19
|
94
|
-
segments:
|
95
|
-
- 1
|
96
|
-
- 1
|
97
|
-
- 0
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
98
67
|
version: 1.1.0
|
99
68
|
type: :runtime
|
100
|
-
version_requirements: *id005
|
101
|
-
- !ruby/object:Gem::Dependency
|
102
|
-
name: mocha
|
103
69
|
prerelease: false
|
104
|
-
|
70
|
+
version_requirements: *2157663580
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: mocha
|
73
|
+
requirement: &2157663000 !ruby/object:Gem::Requirement
|
105
74
|
none: false
|
106
|
-
requirements:
|
107
|
-
- -
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
|
110
|
-
segments:
|
111
|
-
- 0
|
112
|
-
version: "0"
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
113
79
|
type: :development
|
114
|
-
|
115
|
-
|
116
|
-
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *2157663000
|
82
|
+
description: Capistrano is a utility and framework for executing commands in parallel
|
83
|
+
on multiple remote machines, via SSH.
|
84
|
+
email:
|
117
85
|
- jamis@jamisbuck.org
|
118
86
|
- lee.hambley@gmail.com
|
119
|
-
executables:
|
87
|
+
executables:
|
120
88
|
- cap
|
121
89
|
- capify
|
122
90
|
extensions: []
|
123
|
-
|
124
|
-
extra_rdoc_files:
|
91
|
+
extra_rdoc_files:
|
125
92
|
- README.mdown
|
126
|
-
files:
|
93
|
+
files:
|
127
94
|
- .gitignore
|
128
95
|
- .rvmrc
|
129
96
|
- CHANGELOG
|
130
97
|
- Gemfile
|
131
98
|
- README.mdown
|
132
99
|
- Rakefile
|
133
|
-
- VERSION
|
134
100
|
- bin/cap
|
135
101
|
- bin/capify
|
136
102
|
- capistrano.gemspec
|
@@ -228,6 +194,7 @@ files:
|
|
228
194
|
- test/fixtures/config.rb
|
229
195
|
- test/fixtures/custom.rb
|
230
196
|
- test/logger_test.rb
|
197
|
+
- test/recipes_test.rb
|
231
198
|
- test/role_test.rb
|
232
199
|
- test/server_definition_test.rb
|
233
200
|
- test/shell_test.rb
|
@@ -238,40 +205,29 @@ files:
|
|
238
205
|
has_rdoc: true
|
239
206
|
homepage: http://github.com/capistrano/capistrano
|
240
207
|
licenses: []
|
241
|
-
|
242
208
|
post_install_message:
|
243
209
|
rdoc_options: []
|
244
|
-
|
245
|
-
require_paths:
|
210
|
+
require_paths:
|
246
211
|
- lib
|
247
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
212
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
248
213
|
none: false
|
249
|
-
requirements:
|
250
|
-
- -
|
251
|
-
- !ruby/object:Gem::Version
|
252
|
-
|
253
|
-
|
254
|
-
- 0
|
255
|
-
version: "0"
|
256
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
214
|
+
requirements:
|
215
|
+
- - ! '>='
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: '0'
|
218
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
219
|
none: false
|
258
|
-
requirements:
|
259
|
-
- -
|
260
|
-
- !ruby/object:Gem::Version
|
261
|
-
|
262
|
-
segments:
|
263
|
-
- 1
|
264
|
-
- 3
|
265
|
-
- 1
|
266
|
-
version: 1.3.1
|
220
|
+
requirements:
|
221
|
+
- - ! '>='
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: '0'
|
267
224
|
requirements: []
|
268
|
-
|
269
225
|
rubyforge_project:
|
270
226
|
rubygems_version: 1.6.2
|
271
227
|
signing_key:
|
272
228
|
specification_version: 3
|
273
229
|
summary: Capistrano - Welcome to easy deployment with Ruby over SSH
|
274
|
-
test_files:
|
230
|
+
test_files:
|
275
231
|
- test/cli/execute_test.rb
|
276
232
|
- test/cli/help_test.rb
|
277
233
|
- test/cli/options_test.rb
|
@@ -306,6 +262,7 @@ test_files:
|
|
306
262
|
- test/fixtures/config.rb
|
307
263
|
- test/fixtures/custom.rb
|
308
264
|
- test/logger_test.rb
|
265
|
+
- test/recipes_test.rb
|
309
266
|
- test/role_test.rb
|
310
267
|
- test/server_definition_test.rb
|
311
268
|
- test/shell_test.rb
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.6.0
|