capistrano 2.6.1.pre → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|