capistrano 2.1.0 → 3.0.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.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +89 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +674 -0
  7. data/README.md +226 -0
  8. data/Rakefile +5 -0
  9. data/bin/cap +2 -3
  10. data/bin/capify +7 -77
  11. data/capistrano-public_cert.pem +22 -0
  12. data/capistrano.gemspec +35 -0
  13. data/features/deploy.feature +52 -0
  14. data/features/installation.feature +16 -0
  15. data/features/remote_file_task.feature +14 -0
  16. data/features/step_definitions/assertions.rb +90 -0
  17. data/features/step_definitions/cap_commands.rb +8 -0
  18. data/features/step_definitions/setup.rb +25 -0
  19. data/features/support/env.rb +12 -0
  20. data/features/support/remote_command_helpers.rb +20 -0
  21. data/lib/Capfile +3 -0
  22. data/lib/capistrano/all.rb +16 -0
  23. data/lib/capistrano/application.rb +60 -0
  24. data/lib/capistrano/configuration/question.rb +42 -0
  25. data/lib/capistrano/configuration/server.rb +133 -0
  26. data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
  27. data/lib/capistrano/configuration/servers.rb +53 -58
  28. data/lib/capistrano/configuration.rb +84 -30
  29. data/lib/capistrano/console.rb +1 -0
  30. data/lib/capistrano/defaults.rb +13 -0
  31. data/lib/capistrano/deploy.rb +3 -0
  32. data/lib/capistrano/dotfile.rb +3 -0
  33. data/lib/capistrano/dsl/env.rb +64 -0
  34. data/lib/capistrano/dsl/paths.rb +94 -0
  35. data/lib/capistrano/dsl/stages.rb +15 -0
  36. data/lib/capistrano/dsl/task_enhancements.rb +53 -0
  37. data/lib/capistrano/dsl.rb +48 -0
  38. data/lib/capistrano/git.rb +1 -0
  39. data/lib/capistrano/hg.rb +1 -0
  40. data/lib/capistrano/i18n.rb +34 -0
  41. data/lib/capistrano/install.rb +1 -0
  42. data/lib/capistrano/setup.rb +21 -0
  43. data/lib/capistrano/tasks/console.rake +21 -0
  44. data/lib/capistrano/tasks/deploy.rake +204 -0
  45. data/lib/capistrano/tasks/framework.rake +67 -0
  46. data/lib/capistrano/tasks/git.rake +62 -0
  47. data/lib/capistrano/tasks/hg.rake +39 -0
  48. data/lib/capistrano/tasks/install.rake +39 -0
  49. data/lib/capistrano/templates/Capfile +26 -0
  50. data/lib/capistrano/templates/deploy.rb.erb +40 -0
  51. data/lib/capistrano/templates/stage.rb.erb +42 -0
  52. data/lib/capistrano/version.rb +1 -20
  53. data/lib/capistrano/version_validator.rb +37 -0
  54. data/lib/capistrano.rb +0 -2
  55. data/spec/integration/dsl_spec.rb +344 -0
  56. data/spec/integration_spec_helper.rb +7 -0
  57. data/spec/lib/capistrano/application_spec.rb +61 -0
  58. data/spec/lib/capistrano/configuration/question_spec.rb +54 -0
  59. data/spec/lib/capistrano/configuration/server_spec.rb +249 -0
  60. data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
  61. data/spec/lib/capistrano/configuration/servers_spec.rb +184 -0
  62. data/spec/lib/capistrano/configuration_spec.rb +101 -0
  63. data/spec/lib/capistrano/dsl/env_spec.rb +10 -0
  64. data/spec/lib/capistrano/dsl/paths_spec.rb +69 -0
  65. data/spec/lib/capistrano/dsl_spec.rb +63 -0
  66. data/spec/lib/capistrano/version_validator_spec.rb +103 -0
  67. data/spec/lib/capistrano_spec.rb +8 -0
  68. data/spec/spec_helper.rb +15 -0
  69. data/spec/support/.gitignore +1 -0
  70. data/spec/support/Vagrantfile +13 -0
  71. data/spec/support/matchers.rb +5 -0
  72. data/spec/support/tasks/database.cap +11 -0
  73. data/spec/support/test_app.rb +138 -0
  74. metadata +251 -179
  75. data/CHANGELOG +0 -512
  76. data/MIT-LICENSE +0 -20
  77. data/README +0 -43
  78. data/examples/sample.rb +0 -14
  79. data/lib/capistrano/callback.rb +0 -45
  80. data/lib/capistrano/cli/execute.rb +0 -82
  81. data/lib/capistrano/cli/help.rb +0 -102
  82. data/lib/capistrano/cli/help.txt +0 -53
  83. data/lib/capistrano/cli/options.rb +0 -183
  84. data/lib/capistrano/cli/ui.rb +0 -28
  85. data/lib/capistrano/cli.rb +0 -47
  86. data/lib/capistrano/command.rb +0 -161
  87. data/lib/capistrano/configuration/actions/file_transfer.rb +0 -35
  88. data/lib/capistrano/configuration/actions/inspect.rb +0 -46
  89. data/lib/capistrano/configuration/actions/invocation.rb +0 -134
  90. data/lib/capistrano/configuration/callbacks.rb +0 -148
  91. data/lib/capistrano/configuration/connections.rb +0 -159
  92. data/lib/capistrano/configuration/execution.rb +0 -126
  93. data/lib/capistrano/configuration/loading.rb +0 -198
  94. data/lib/capistrano/configuration/namespaces.rb +0 -196
  95. data/lib/capistrano/configuration/roles.rb +0 -51
  96. data/lib/capistrano/configuration/variables.rb +0 -127
  97. data/lib/capistrano/errors.rb +0 -15
  98. data/lib/capistrano/extensions.rb +0 -57
  99. data/lib/capistrano/gateway.rb +0 -131
  100. data/lib/capistrano/logger.rb +0 -59
  101. data/lib/capistrano/recipes/compat.rb +0 -32
  102. data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
  103. data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -46
  104. data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -96
  105. data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
  106. data/lib/capistrano/recipes/deploy/scm/base.rb +0 -192
  107. data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
  108. data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -151
  109. data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -85
  110. data/lib/capistrano/recipes/deploy/scm/git.rb +0 -191
  111. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -129
  112. data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -126
  113. data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -114
  114. data/lib/capistrano/recipes/deploy/scm.rb +0 -19
  115. data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -64
  116. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
  117. data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -144
  118. data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
  119. data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
  120. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -47
  121. data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
  122. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  123. data/lib/capistrano/recipes/deploy.rb +0 -494
  124. data/lib/capistrano/recipes/standard.rb +0 -37
  125. data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
  126. data/lib/capistrano/recipes/upgrade.rb +0 -33
  127. data/lib/capistrano/server_definition.rb +0 -51
  128. data/lib/capistrano/shell.rb +0 -256
  129. data/lib/capistrano/ssh.rb +0 -109
  130. data/lib/capistrano/task_definition.rb +0 -69
  131. data/lib/capistrano/upload.rb +0 -146
  132. data/test/cli/execute_test.rb +0 -132
  133. data/test/cli/help_test.rb +0 -139
  134. data/test/cli/options_test.rb +0 -226
  135. data/test/cli/ui_test.rb +0 -28
  136. data/test/cli_test.rb +0 -17
  137. data/test/command_test.rb +0 -309
  138. data/test/configuration/actions/file_transfer_test.rb +0 -40
  139. data/test/configuration/actions/inspect_test.rb +0 -62
  140. data/test/configuration/actions/invocation_test.rb +0 -202
  141. data/test/configuration/callbacks_test.rb +0 -206
  142. data/test/configuration/connections_test.rb +0 -288
  143. data/test/configuration/execution_test.rb +0 -159
  144. data/test/configuration/loading_test.rb +0 -127
  145. data/test/configuration/namespace_dsl_test.rb +0 -297
  146. data/test/configuration/roles_test.rb +0 -47
  147. data/test/configuration/servers_test.rb +0 -90
  148. data/test/configuration/variables_test.rb +0 -180
  149. data/test/configuration_test.rb +0 -81
  150. data/test/deploy/scm/accurev_test.rb +0 -23
  151. data/test/deploy/scm/base_test.rb +0 -55
  152. data/test/deploy/scm/git_test.rb +0 -112
  153. data/test/deploy/strategy/copy_test.rb +0 -147
  154. data/test/extensions_test.rb +0 -69
  155. data/test/fixtures/cli_integration.rb +0 -5
  156. data/test/fixtures/config.rb +0 -5
  157. data/test/fixtures/custom.rb +0 -3
  158. data/test/gateway_test.rb +0 -167
  159. data/test/logger_test.rb +0 -123
  160. data/test/server_definition_test.rb +0 -108
  161. data/test/shell_test.rb +0 -64
  162. data/test/ssh_test.rb +0 -97
  163. data/test/task_definition_test.rb +0 -101
  164. data/test/upload_test.rb +0 -131
  165. data/test/utils.rb +0 -42
  166. data/test/version_test.rb +0 -24
@@ -1,206 +0,0 @@
1
- require "#{File.dirname(__FILE__)}/../utils"
2
- require 'capistrano/configuration/callbacks'
3
-
4
- class ConfigurationCallbacksTest < Test::Unit::TestCase
5
- class MockConfig
6
- attr_reader :original_initialize_called
7
- attr_reader :called
8
-
9
- def initialize
10
- @original_initialize_called = true
11
- @called = []
12
- end
13
-
14
- def execute_task(task)
15
- @called << task
16
- end
17
-
18
- include Capistrano::Configuration::Callbacks
19
- end
20
-
21
- def setup
22
- @config = MockConfig.new
23
- @config.stubs(:logger).returns(stub_everything("logger"))
24
- end
25
-
26
- def test_initialize_should_initialize_callbacks_collection
27
- assert @config.original_initialize_called
28
- assert @config.callbacks.empty?
29
- end
30
-
31
- def test_before_should_delegate_to_on
32
- @config.expects(:on).with(:before, :foo, "bing:blang", {:only => :bar, :zip => :zing})
33
- @config.before :bar, :foo, "bing:blang", :zip => :zing
34
- end
35
-
36
- def test_after_should_delegate_to_on
37
- @config.expects(:on).with(:after, :foo, "bing:blang", {:only => :bar, :zip => :zing})
38
- @config.after :bar, :foo, "bing:blang", :zip => :zing
39
- end
40
-
41
- def test_on_with_single_reference_should_add_task_callback
42
- @config.on :before, :a_test
43
- assert_equal 1, @config.callbacks[:before].length
44
- assert_equal :a_test, @config.callbacks[:before][0].source
45
- @config.expects(:find_and_execute_task).with(:a_test)
46
- @config.callbacks[:before][0].call
47
- end
48
-
49
- def test_on_with_multi_reference_should_add_all_as_task_callback
50
- @config.on :before, :first, :second, :third
51
- assert_equal 3, @config.callbacks[:before].length
52
- assert_equal %w(first second third), @config.callbacks[:before].map { |c| c.source.to_s }
53
- end
54
-
55
- def test_on_with_block_should_add_block_as_proc_callback
56
- called = false
57
- @config.on(:before) { called = true }
58
- assert_equal 1, @config.callbacks[:before].length
59
- assert_instance_of Proc, @config.callbacks[:before][0].source
60
- @config.callbacks[:before][0].call
61
- assert called
62
- end
63
-
64
- def test_on_with_single_only_should_set_only_as_string_array_on_all_references
65
- @config.on :before, :first, "second:third", :only => :primary
66
- assert_equal 2, @config.callbacks[:before].length
67
- assert @config.callbacks[:before].all? { |c| c.only == %w(primary) }
68
- end
69
-
70
- def test_on_with_multi_only_should_set_only_as_string_array_on_all_references
71
- @config.on :before, :first, "second:third", :only => [:primary, "other:one"]
72
- assert_equal 2, @config.callbacks[:before].length
73
- assert @config.callbacks[:before].all? { |c| c.only == %w(primary other:one) }
74
- end
75
-
76
- def test_on_with_single_except_should_set_except_as_string_array_on_all_references
77
- @config.on :before, :first, "second:third", :except => :primary
78
- assert_equal 2, @config.callbacks[:before].length
79
- assert @config.callbacks[:before].all? { |c| c.except == %w(primary) }
80
- end
81
-
82
- def test_on_with_multi_except_should_set_except_as_string_array_on_all_references
83
- @config.on :before, :first, "second:third", :except => [:primary, "other:one"]
84
- assert_equal 2, @config.callbacks[:before].length
85
- assert @config.callbacks[:before].all? { |c| c.except == %w(primary other:one) }
86
- end
87
-
88
- def test_on_with_only_and_block_should_set_only_as_string_array
89
- @config.on(:before, :only => :primary) { blah }
90
- assert_equal 1, @config.callbacks[:before].length
91
- assert_equal %w(primary), @config.callbacks[:before].first.only
92
- end
93
-
94
- def test_on_with_except_and_block_should_set_except_as_string_array
95
- @config.on(:before, :except => :primary) { blah }
96
- assert_equal 1, @config.callbacks[:before].length
97
- assert_equal %w(primary), @config.callbacks[:before].first.except
98
- end
99
-
100
- def test_trigger_without_constraints_should_invoke_all_callbacks
101
- task = stub(:fully_qualified_name => "any:old:thing")
102
- @config.on(:before, :first, "second:third")
103
- @config.on(:after, :another, "and:another")
104
- @config.expects(:find_and_execute_task).with(:first)
105
- @config.expects(:find_and_execute_task).with("second:third")
106
- @config.expects(:find_and_execute_task).with(:another).never
107
- @config.expects(:find_and_execute_task).with("and:another").never
108
- @config.trigger(:before, task)
109
- end
110
-
111
- def test_trigger_with_only_constraint_should_invoke_only_matching_callbacks
112
- task = stub(:fully_qualified_name => "any:old:thing")
113
- @config.on(:before, :first)
114
- @config.on(:before, "second:third", :only => "any:old:thing")
115
- @config.on(:before, "this:too", :only => "any:other:thing")
116
- @config.on(:after, :another, "and:another")
117
- @config.expects(:find_and_execute_task).with(:first)
118
- @config.expects(:find_and_execute_task).with("second:third")
119
- @config.expects(:find_and_execute_task).with("this:too").never
120
- @config.expects(:find_and_execute_task).with(:another).never
121
- @config.expects(:find_and_execute_task).with("and:another").never
122
- @config.trigger(:before, task)
123
- end
124
-
125
- def test_trigger_with_except_constraint_should_invoke_anything_but_matching_callbacks
126
- task = stub(:fully_qualified_name => "any:old:thing")
127
- @config.on(:before, :first)
128
- @config.on(:before, "second:third", :except => "any:old:thing")
129
- @config.on(:before, "this:too", :except => "any:other:thing")
130
- @config.on(:after, :another, "and:another")
131
- @config.expects(:find_and_execute_task).with(:first)
132
- @config.expects(:find_and_execute_task).with("second:third").never
133
- @config.expects(:find_and_execute_task).with("this:too")
134
- @config.expects(:find_and_execute_task).with(:another).never
135
- @config.expects(:find_and_execute_task).with("and:another").never
136
- @config.trigger(:before, task)
137
- end
138
-
139
- def test_trigger_without_task_should_invoke_all_callbacks_for_that_event
140
- task = stub(:fully_qualified_name => "any:old:thing")
141
- @config.on(:before, :first)
142
- @config.on(:before, "second:third", :except => "any:old:thing")
143
- @config.on(:before, "this:too", :except => "any:other:thing")
144
- @config.on(:after, :another, "and:another")
145
- @config.expects(:find_and_execute_task).with(:first)
146
- @config.expects(:find_and_execute_task).with("second:third")
147
- @config.expects(:find_and_execute_task).with("this:too")
148
- @config.expects(:find_and_execute_task).with(:another).never
149
- @config.expects(:find_and_execute_task).with("and:another").never
150
- @config.trigger(:before)
151
- end
152
-
153
- def test_execute_task_without_named_hooks_should_just_call_task
154
- ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
155
- task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
156
-
157
- ns.stubs(:search_task).returns(nil)
158
-
159
- @config.execute_task(task)
160
- assert_equal [task], @config.called
161
- end
162
-
163
- def test_execute_task_with_named_before_hook_should_call_named_before_hook
164
- ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
165
- task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
166
- before_task = stub(:fully_qualified_name => "any:old:before_thing", :name => "before_thing", :namespace => ns)
167
-
168
- ns.stubs(:search_task).returns(nil)
169
- ns.expects(:search_task).with("before_thing").returns(before_task)
170
-
171
- @config.execute_task(task)
172
- assert_equal [before_task, task], @config.called
173
- end
174
-
175
- def test_execute_task_with_named_after_hook_should_call_named_after_hook
176
- ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
177
- task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
178
- after_task = stub(:fully_qualified_name => "any:old:after_thing", :name => "after_thing", :namespace => ns)
179
-
180
- ns.stubs(:search_task).returns(nil)
181
- ns.expects(:search_task).with("after_thing").returns(after_task)
182
-
183
- @config.execute_task(task)
184
- assert_equal [task, after_task], @config.called
185
- end
186
-
187
- def test_execute_task_with_on_hooks_should_trigger_hooks_around_task
188
- ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
189
- task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
190
- before_task = stub(:fully_qualified_name => "any:old:before_thing", :name => "before_thing", :namespace => ns)
191
- after_task = stub(:fully_qualified_name => "any:old:after_thing", :name => "after_thing", :namespace => ns)
192
-
193
- ns.stubs(:search_task).returns(nil)
194
- ns.expects(:search_task).with("before_thing").returns(before_task)
195
- ns.expects(:search_task).with("after_thing").returns(after_task)
196
-
197
- @config.before("any:old:thing", :first_this, :then_this)
198
- @config.after("any:old:thing", :and_then_this, :lastly_this)
199
-
200
- [:first_this, :then_this, :and_then_this, :lastly_this].each do |t|
201
- @config.expects(:find_and_execute_task).with(t)
202
- end
203
-
204
- @config.execute_task(task)
205
- end
206
- end
@@ -1,288 +0,0 @@
1
- require "#{File.dirname(__FILE__)}/../utils"
2
- require 'capistrano/configuration/connections'
3
-
4
- class ConfigurationConnectionsTest < Test::Unit::TestCase
5
- class MockConfig
6
- attr_reader :original_initialize_called
7
- attr_reader :values
8
- attr_accessor :current_task
9
-
10
- def initialize
11
- @original_initialize_called = true
12
- @values = {}
13
- end
14
-
15
- def fetch(*args)
16
- @values.fetch(*args)
17
- end
18
-
19
- def [](key)
20
- @values[key]
21
- end
22
-
23
- def exists?(key)
24
- @values.key?(key)
25
- end
26
-
27
- include Capistrano::Configuration::Connections
28
- end
29
-
30
- def setup
31
- @config = MockConfig.new
32
- @config.stubs(:logger).returns(stub_everything)
33
- @ssh_options = {
34
- :user => "jamis",
35
- :port => 8080,
36
- :password => "g00b3r",
37
- :ssh_options => { :debug => :verbose }
38
- }
39
- end
40
-
41
- def test_initialize_should_initialize_collections_and_call_original_initialize
42
- assert @config.original_initialize_called
43
- assert @config.sessions.empty?
44
- end
45
-
46
- def test_connection_factory_should_return_default_connection_factory_instance
47
- factory = @config.connection_factory
48
- assert_instance_of Capistrano::Configuration::Connections::DefaultConnectionFactory, factory
49
- end
50
-
51
- def test_connection_factory_instance_should_be_cached
52
- assert_same @config.connection_factory, @config.connection_factory
53
- end
54
-
55
- def test_default_connection_factory_honors_config_options
56
- server = server("capistrano")
57
- Capistrano::SSH.expects(:connect).with(server, @config).returns(:session)
58
- assert_equal :session, @config.connection_factory.connect_to(server)
59
- end
60
-
61
- def test_connection_factory_should_return_gateway_instance_if_gateway_variable_is_set
62
- @config.values[:gateway] = "capistrano"
63
- server = server("capistrano")
64
- Capistrano::SSH.expects(:connect).with { |s,| s.host == "capistrano" }.yields(stub_everything)
65
- assert_instance_of Capistrano::Gateway, @config.connection_factory
66
- end
67
-
68
- def test_connection_factory_as_gateway_should_honor_config_options
69
- @config.values[:gateway] = "capistrano"
70
- @config.values.update(@ssh_options)
71
- Capistrano::SSH.expects(:connect).with { |s,opts| s.host == "capistrano" && opts == @config }.yields(stub_everything)
72
- assert_instance_of Capistrano::Gateway, @config.connection_factory
73
- end
74
-
75
- def test_establish_connections_to_should_accept_a_single_nonarray_parameter
76
- Capistrano::SSH.expects(:connect).with { |s,| s.host == "capistrano" }.returns(:success)
77
- assert @config.sessions.empty?
78
- @config.establish_connections_to(server("capistrano"))
79
- assert ["capistrano"], @config.sessions.keys
80
- end
81
-
82
- def test_establish_connections_to_should_accept_an_array
83
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
84
- assert @config.sessions.empty?
85
- @config.establish_connections_to(%w(cap1 cap2 cap3).map { |s| server(s) })
86
- assert %w(cap1 cap2 cap3), @config.sessions.keys.sort
87
- end
88
-
89
- def test_establish_connections_to_should_not_attempt_to_reestablish_existing_connections
90
- Capistrano::SSH.expects(:connect).times(2).returns(:success)
91
- @config.sessions[server("cap1")] = :ok
92
- @config.establish_connections_to(%w(cap1 cap2 cap3).map { |s| server(s) })
93
- assert %w(cap1 cap2 cap3), @config.sessions.keys.sort.map { |s| s.host }
94
- end
95
-
96
- def test_establish_connections_to_should_raise_one_connection_error_on_failure
97
- Capistrano::SSH.expects(:connect).times(2).raises(Exception)
98
- assert_raises(Capistrano::ConnectionError) {
99
- @config.establish_connections_to(%w(cap1 cap2).map { |s| server(s) })
100
- }
101
- end
102
-
103
- def test_connection_error_should_include_accessor_with_host_array
104
- Capistrano::SSH.expects(:connect).times(2).raises(Exception)
105
-
106
- begin
107
- @config.establish_connections_to(%w(cap1 cap2).map { |s| server(s) })
108
- flunk "expected an exception to be raised"
109
- rescue Capistrano::ConnectionError => e
110
- assert e.respond_to?(:hosts)
111
- assert_equal %w(cap1 cap2), e.hosts.map { |h| h.to_s }
112
- end
113
- end
114
-
115
- def test_connection_error_should_only_include_failed_hosts
116
- Capistrano::SSH.expects(:connect).times(2).raises(Exception).then.returns(:success)
117
-
118
- begin
119
- @config.establish_connections_to(%w(cap1 cap2).map { |s| server(s) })
120
- flunk "expected an exception to be raised"
121
- rescue Capistrano::ConnectionError => e
122
- assert_equal %w(cap1), e.hosts.map { |h| h.to_s }
123
- end
124
- end
125
-
126
- def test_execute_on_servers_should_require_a_block
127
- assert_raises(ArgumentError) { @config.execute_on_servers }
128
- end
129
-
130
- def test_execute_on_servers_without_current_task_should_call_find_servers
131
- list = [server("first"), server("second")]
132
- @config.expects(:find_servers).with(:a => :b, :c => :d).returns(list)
133
- @config.expects(:establish_connections_to).with(list).returns(:done)
134
- @config.execute_on_servers(:a => :b, :c => :d) do |result|
135
- assert_equal list, result
136
- end
137
- end
138
-
139
- def test_execute_on_servers_without_current_task_should_raise_error_if_no_matching_servers
140
- @config.expects(:find_servers).with(:a => :b, :c => :d).returns([])
141
- assert_raises(Capistrano::NoMatchingServersError) { @config.execute_on_servers(:a => :b, :c => :d) { |list| } }
142
- end
143
-
144
- def test_execute_on_servers_should_raise_an_error_if_the_current_task_has_no_matching_servers_by_default
145
- @config.current_task = mock_task
146
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([])
147
- assert_raises(Capistrano::NoMatchingServersError) do
148
- @config.execute_on_servers do
149
- flunk "should not get here"
150
- end
151
- end
152
- end
153
-
154
- def test_execute_on_servers_should_determine_server_list_from_active_task
155
- assert @config.sessions.empty?
156
- @config.current_task = mock_task
157
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2"), server("cap3")])
158
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
159
- @config.execute_on_servers {}
160
- assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map { |s| s.host }
161
- end
162
-
163
- def test_execute_on_servers_should_yield_server_list_to_block
164
- assert @config.sessions.empty?
165
- @config.current_task = mock_task
166
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2"), server("cap3")])
167
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
168
- block_called = false
169
- @config.execute_on_servers do |servers|
170
- block_called = true
171
- assert servers.detect { |s| s.host == "cap1" }
172
- assert servers.detect { |s| s.host == "cap2" }
173
- assert servers.detect { |s| s.host == "cap3" }
174
- assert servers.all? { |s| @config.sessions[s] }
175
- end
176
- assert block_called
177
- end
178
-
179
- def test_execute_on_servers_with_once_option_should_establish_connection_to_and_yield_only_the_first_server
180
- assert @config.sessions.empty?
181
- @config.current_task = mock_task
182
- @config.expects(:find_servers_for_task).with(@config.current_task, :once => true).returns([server("cap1"), server("cap2"), server("cap3")])
183
- Capistrano::SSH.expects(:connect).returns(:success)
184
- block_called = false
185
- @config.execute_on_servers(:once => true) do |servers|
186
- block_called = true
187
- assert_equal %w(cap1), servers.map { |s| s.host }
188
- end
189
- assert block_called
190
- assert_equal %w(cap1), @config.sessions.keys.sort.map { |s| s.host }
191
- end
192
-
193
- def test_execute_servers_should_raise_connection_error_on_failure_by_default
194
- @config.current_task = mock_task
195
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1")])
196
- Capistrano::SSH.expects(:connect).raises(Exception)
197
- assert_raises(Capistrano::ConnectionError) {
198
- @config.execute_on_servers do
199
- flunk "expected an exception to be raised"
200
- end
201
- }
202
- end
203
-
204
- def test_execute_servers_should_not_raise_connection_error_on_failure_with_on_errors_continue
205
- @config.current_task = mock_task(:on_error => :continue)
206
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2")])
207
- Capistrano::SSH.expects(:connect).times(2).raises(Exception).then.returns(:success)
208
- assert_nothing_raised {
209
- @config.execute_on_servers do |servers|
210
- assert_equal %w(cap2), servers.map { |s| s.host }
211
- end
212
- }
213
- end
214
-
215
- def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_connection_errors_with_on_errors_continue
216
- list = [server("cap1"), server("cap2")]
217
- @config.current_task = mock_task(:on_error => :continue)
218
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns(list)
219
- Capistrano::SSH.expects(:connect).times(2).raises(Exception).then.returns(:success)
220
- @config.expects(:failed!).with(server("cap1"))
221
- @config.execute_on_servers do |servers|
222
- assert_equal %w(cap2), servers.map { |s| s.host }
223
- end
224
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns(list)
225
- @config.execute_on_servers do |servers|
226
- assert_equal %w(cap2), servers.map { |s| s.host }
227
- end
228
- end
229
-
230
- def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_command_errors_with_on_errors_continue
231
- cap1 = server("cap1")
232
- cap2 = server("cap2")
233
- @config.current_task = mock_task(:on_error => :continue)
234
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
235
- Capistrano::SSH.expects(:connect).times(2).returns(:success)
236
- @config.execute_on_servers do |servers|
237
- error = Capistrano::CommandError.new
238
- error.hosts = [cap1]
239
- raise error
240
- end
241
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
242
- @config.execute_on_servers do |servers|
243
- assert_equal %w(cap2), servers.map { |s| s.host }
244
- end
245
- end
246
-
247
- def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_upload_errors_with_on_errors_continue
248
- cap1 = server("cap1")
249
- cap2 = server("cap2")
250
- @config.current_task = mock_task(:on_error => :continue)
251
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
252
- Capistrano::SSH.expects(:connect).times(2).returns(:success)
253
- @config.execute_on_servers do |servers|
254
- error = Capistrano::UploadError.new
255
- error.hosts = [cap1]
256
- raise error
257
- end
258
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
259
- @config.execute_on_servers do |servers|
260
- assert_equal %w(cap2), servers.map { |s| s.host }
261
- end
262
- end
263
-
264
- def test_connect_should_establish_connections_to_all_servers_in_scope
265
- assert @config.sessions.empty?
266
- @config.current_task = mock_task
267
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2"), server("cap3")])
268
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
269
- @config.connect!
270
- assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map { |s| s.host }
271
- end
272
-
273
- def test_connect_should_honor_once_option
274
- assert @config.sessions.empty?
275
- @config.current_task = mock_task
276
- @config.expects(:find_servers_for_task).with(@config.current_task, :once => true).returns([server("cap1"), server("cap2"), server("cap3")])
277
- Capistrano::SSH.expects(:connect).returns(:success)
278
- @config.connect! :once => true
279
- assert_equal %w(cap1), @config.sessions.keys.sort.map { |s| s.host }
280
- end
281
-
282
- private
283
-
284
- def mock_task(options={})
285
- continue_on_error = options[:on_error] == :continue
286
- stub("task", :fully_qualified_name => "name", :options => options, :continue_on_error? => continue_on_error)
287
- end
288
- end
@@ -1,159 +0,0 @@
1
- require "#{File.dirname(__FILE__)}/../utils"
2
- require 'capistrano/configuration/execution'
3
- require 'capistrano/task_definition'
4
-
5
- class ConfigurationExecutionTest < Test::Unit::TestCase
6
- class MockConfig
7
- attr_reader :tasks, :namespaces, :fully_qualified_name, :parent
8
- attr_reader :state, :original_initialize_called
9
- attr_accessor :logger, :default_task
10
-
11
- def initialize(options={})
12
- @original_initialize_called = true
13
- @tasks = {}
14
- @namespaces = {}
15
- @state = {}
16
- @fully_qualified_name = options[:fqn]
17
- @parent = options[:parent]
18
- @logger = options.delete(:logger)
19
- end
20
-
21
- include Capistrano::Configuration::Execution
22
- end
23
-
24
- def setup
25
- @config = MockConfig.new(:logger => stub(:debug => nil, :info => nil, :important => nil))
26
- @config.stubs(:search_task).returns(nil)
27
- end
28
-
29
- def test_initialize_should_initialize_collections
30
- assert_nil @config.rollback_requests
31
- assert @config.original_initialize_called
32
- assert @config.task_call_frames.empty?
33
- end
34
-
35
- def test_execute_task_should_populate_call_stack
36
- task = new_task @config, :testing
37
- assert_nothing_raised { @config.execute_task(task) }
38
- assert_equal %w(testing), @config.state[:testing][:stack]
39
- assert_nil @config.state[:testing][:history]
40
- assert @config.task_call_frames.empty?
41
- end
42
-
43
- def test_nested_execute_task_should_add_to_call_stack
44
- testing = new_task @config, :testing
45
- outer = new_task(@config, :outer) { execute_task(testing) }
46
-
47
- assert_nothing_raised { @config.execute_task(outer) }
48
- assert_equal %w(outer testing), @config.state[:testing][:stack]
49
- assert_nil @config.state[:testing][:history]
50
- assert @config.task_call_frames.empty?
51
- end
52
-
53
- def test_execute_task_should_execute_in_scope_of_tasks_parent
54
- ns = stub("namespace", :tasks => {}, :default_task => nil, :fully_qualified_name => "ns")
55
- ns.expects(:instance_eval)
56
- testing = new_task ns, :testing
57
- @config.execute_task(testing)
58
- end
59
-
60
- def test_transaction_outside_of_task_should_raise_exception
61
- assert_raises(ScriptError) { @config.transaction {} }
62
- end
63
-
64
- def test_transaction_without_block_should_raise_argument_error
65
- testing = new_task(@config, :testing) { transaction }
66
- assert_raises(ArgumentError) { @config.execute_task(testing) }
67
- end
68
-
69
- def test_transaction_should_initialize_transaction_history
70
- @config.state[:inspector] = stack_inspector
71
- testing = new_task(@config, :testing) { transaction { instance_eval(&state[:inspector]) } }
72
- @config.execute_task(testing)
73
- assert_equal [], @config.state[:testing][:history]
74
- end
75
-
76
- def test_transaction_from_within_transaction_should_not_start_new_transaction
77
- third = new_task(@config, :third, &stack_inspector)
78
- second = new_task(@config, :second) { transaction { execute_task(third) } }
79
- first = new_task(@config, :first) { transaction { execute_task(second) } }
80
- # kind of fragile...not sure how else to check that transaction was only
81
- # really run twice...but if the transaction was REALLY run, logger.info
82
- # will be called once when it starts, and once when it finishes.
83
- @config.logger = mock()
84
- @config.logger.stubs(:debug)
85
- @config.logger.expects(:info).times(2)
86
- @config.execute_task(first)
87
- end
88
-
89
- def test_on_rollback_should_have_no_effect_outside_of_transaction
90
- aaa = new_task(@config, :aaa) { on_rollback { state[:rollback] = true }; raise "boom" }
91
- assert_raises(RuntimeError) { @config.execute_task(aaa) }
92
- assert_nil @config.state[:rollback]
93
- end
94
-
95
- def test_exception_raised_in_transaction_should_call_all_registered_rollback_handlers_in_reverse_order
96
- aaa = new_task(@config, :aaa) { on_rollback { (state[:rollback] ||= []) << :aaa } }
97
- bbb = new_task(@config, :bbb) { on_rollback { (state[:rollback] ||= []) << :bbb } }
98
- ccc = new_task(@config, :ccc) {}
99
- ddd = new_task(@config, :ddd) { on_rollback { (state[:rollback] ||= []) << :ddd }; execute_task(bbb); execute_task(ccc) }
100
- eee = new_task(@config, :eee) { transaction { execute_task(ddd); execute_task(aaa); raise "boom" } }
101
- assert_raises(RuntimeError) do
102
- @config.execute_task(eee)
103
- end
104
- assert_equal [:aaa, :bbb, :ddd], @config.state[:rollback]
105
- assert_nil @config.rollback_requests
106
- assert @config.task_call_frames.empty?
107
- end
108
-
109
- def test_exception_during_rollback_should_simply_be_logged_and_ignored
110
- aaa = new_task(@config, :aaa) { on_rollback { state[:aaa] = true; raise LoadError, "ouch" }; execute_task(bbb) }
111
- bbb = new_task(@config, :bbb) { raise MadError, "boom" }
112
- ccc = new_task(@config, :ccc) { transaction { execute_task(aaa) } }
113
- assert_raises(NameError) do
114
- @config.execute_task(ccc)
115
- end
116
- assert @config.state[:aaa]
117
- end
118
-
119
- def test_find_and_execute_task_should_raise_error_when_task_cannot_be_found
120
- @config.expects(:find_task).with("path:to:task").returns(nil)
121
- assert_raises(Capistrano::NoSuchTaskError) { @config.find_and_execute_task("path:to:task") }
122
- end
123
-
124
- def test_find_and_execute_task_should_execute_task_when_task_is_found
125
- @config.expects(:find_task).with("path:to:task").returns(:found)
126
- @config.expects(:execute_task).with(:found)
127
- assert_nothing_raised { @config.find_and_execute_task("path:to:task") }
128
- end
129
-
130
- def test_find_and_execute_task_with_before_option_should_trigger_callback
131
- @config.expects(:find_task).with("path:to:task").returns(:found)
132
- @config.expects(:trigger).with(:incoming, :found)
133
- @config.expects(:execute_task).with(:found)
134
- @config.find_and_execute_task("path:to:task", :before => :incoming)
135
- end
136
-
137
- def test_find_and_execute_task_with_after_option_should_trigger_callback
138
- @config.expects(:find_task).with("path:to:task").returns(:found)
139
- @config.expects(:trigger).with(:outgoing, :found)
140
- @config.expects(:execute_task).with(:found)
141
- @config.find_and_execute_task("path:to:task", :after => :outgoing)
142
- end
143
-
144
- private
145
-
146
- def stack_inspector
147
- Proc.new do
148
- (state[:trail] ||= []) << current_task.fully_qualified_name
149
- data = state[current_task.name] = {}
150
- data[:stack] = task_call_frames.map { |frame| frame.task.fully_qualified_name }
151
- data[:history] = rollback_requests && rollback_requests.map { |frame| frame.task.fully_qualified_name }
152
- end
153
- end
154
-
155
- def new_task(namespace, name, options={}, &block)
156
- block ||= stack_inspector
157
- namespace.tasks[name] = Capistrano::TaskDefinition.new(name, namespace, &block)
158
- end
159
- end