capistrano 2.8.0 → 3.19.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 (239) hide show
  1. checksums.yaml +7 -0
  2. data/.docker/Dockerfile +7 -0
  3. data/.docker/ssh_key_rsa +49 -0
  4. data/.docker/ssh_key_rsa.pub +1 -0
  5. data/.docker/ubuntu_setup.sh +23 -0
  6. data/.github/issue_template.md +19 -0
  7. data/.github/pull_request_template.md +22 -0
  8. data/.github/release-drafter.yml +25 -0
  9. data/.github/workflows/ci.yml +80 -0
  10. data/.github/workflows/release-drafter.yml +18 -0
  11. data/.gitignore +23 -8
  12. data/.rubocop.yml +62 -0
  13. data/CHANGELOG.md +1 -0
  14. data/CONTRIBUTING.md +63 -0
  15. data/DEVELOPMENT.md +112 -0
  16. data/Gemfile +42 -9
  17. data/LICENSE.txt +21 -0
  18. data/README.md +221 -0
  19. data/RELEASING.md +17 -0
  20. data/Rakefile +17 -8
  21. data/UPGRADING-3.7.md +86 -0
  22. data/bin/cap +2 -3
  23. data/bin/capify +7 -89
  24. data/capistrano.gemspec +29 -43
  25. data/docker-compose.yml +8 -0
  26. data/features/configuration.feature +28 -0
  27. data/features/deploy.feature +92 -0
  28. data/features/deploy_failure.feature +17 -0
  29. data/features/doctor.feature +11 -0
  30. data/features/installation.feature +21 -0
  31. data/features/sshconnect.feature +11 -0
  32. data/features/stage_failure.feature +9 -0
  33. data/features/step_definitions/assertions.rb +162 -0
  34. data/features/step_definitions/cap_commands.rb +21 -0
  35. data/features/step_definitions/setup.rb +91 -0
  36. data/features/subdirectory.feature +9 -0
  37. data/features/support/docker_gateway.rb +53 -0
  38. data/features/support/env.rb +1 -0
  39. data/features/support/remote_command_helpers.rb +29 -0
  40. data/features/support/remote_ssh_helpers.rb +33 -0
  41. data/lib/Capfile +3 -0
  42. data/lib/capistrano/all.rb +17 -0
  43. data/lib/capistrano/application.rb +153 -0
  44. data/lib/capistrano/configuration/empty_filter.rb +9 -0
  45. data/lib/capistrano/configuration/filter.rb +26 -0
  46. data/lib/capistrano/configuration/host_filter.rb +29 -0
  47. data/lib/capistrano/configuration/null_filter.rb +9 -0
  48. data/lib/capistrano/configuration/plugin_installer.rb +51 -0
  49. data/lib/capistrano/configuration/question.rb +76 -0
  50. data/lib/capistrano/configuration/role_filter.rb +29 -0
  51. data/lib/capistrano/configuration/scm_resolver.rb +149 -0
  52. data/lib/capistrano/configuration/server.rb +137 -0
  53. data/lib/capistrano/configuration/servers.rb +56 -96
  54. data/lib/capistrano/configuration/validated_variables.rb +110 -0
  55. data/lib/capistrano/configuration/variables.rb +79 -94
  56. data/lib/capistrano/configuration.rb +178 -33
  57. data/lib/capistrano/console.rb +1 -0
  58. data/lib/capistrano/defaults.rb +36 -0
  59. data/lib/capistrano/deploy.rb +3 -0
  60. data/lib/capistrano/doctor/environment_doctor.rb +19 -0
  61. data/lib/capistrano/doctor/gems_doctor.rb +45 -0
  62. data/lib/capistrano/doctor/output_helpers.rb +79 -0
  63. data/lib/capistrano/doctor/servers_doctor.rb +105 -0
  64. data/lib/capistrano/doctor/variables_doctor.rb +74 -0
  65. data/lib/capistrano/doctor.rb +6 -0
  66. data/lib/capistrano/dotfile.rb +2 -0
  67. data/lib/capistrano/dsl/env.rb +43 -0
  68. data/lib/capistrano/dsl/paths.rb +89 -0
  69. data/lib/capistrano/dsl/stages.rb +31 -0
  70. data/lib/capistrano/dsl/task_enhancements.rb +61 -0
  71. data/lib/capistrano/dsl.rb +95 -0
  72. data/lib/capistrano/framework.rb +2 -0
  73. data/lib/capistrano/i18n.rb +46 -0
  74. data/lib/capistrano/immutable_task.rb +30 -0
  75. data/lib/capistrano/install.rb +1 -0
  76. data/lib/capistrano/plugin.rb +95 -0
  77. data/lib/capistrano/proc_helpers.rb +13 -0
  78. data/lib/capistrano/scm/git.rb +105 -0
  79. data/lib/capistrano/scm/hg.rb +55 -0
  80. data/lib/capistrano/scm/plugin.rb +13 -0
  81. data/lib/capistrano/scm/svn.rb +56 -0
  82. data/lib/capistrano/scm/tasks/git.rake +84 -0
  83. data/lib/capistrano/scm/tasks/hg.rake +53 -0
  84. data/lib/capistrano/scm/tasks/svn.rake +53 -0
  85. data/lib/capistrano/scm.rb +115 -0
  86. data/lib/capistrano/setup.rb +36 -0
  87. data/lib/capistrano/tasks/console.rake +25 -0
  88. data/lib/capistrano/tasks/deploy.rake +280 -0
  89. data/lib/capistrano/tasks/doctor.rake +24 -0
  90. data/lib/capistrano/tasks/framework.rake +67 -0
  91. data/lib/capistrano/tasks/install.rake +41 -0
  92. data/lib/capistrano/templates/Capfile +38 -0
  93. data/lib/capistrano/templates/deploy.rb.erb +39 -0
  94. data/lib/capistrano/templates/stage.rb.erb +61 -0
  95. data/lib/capistrano/upload_task.rb +9 -0
  96. data/lib/capistrano/version.rb +1 -14
  97. data/lib/capistrano/version_validator.rb +32 -0
  98. data/lib/capistrano.rb +0 -3
  99. data/spec/integration/dsl_spec.rb +632 -0
  100. data/spec/integration_spec_helper.rb +5 -0
  101. data/spec/lib/capistrano/application_spec.rb +60 -0
  102. data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
  103. data/spec/lib/capistrano/configuration/filter_spec.rb +109 -0
  104. data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
  105. data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
  106. data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
  107. data/spec/lib/capistrano/configuration/question_spec.rb +92 -0
  108. data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
  109. data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +56 -0
  110. data/spec/lib/capistrano/configuration/server_spec.rb +309 -0
  111. data/spec/lib/capistrano/configuration/servers_spec.rb +331 -0
  112. data/spec/lib/capistrano/configuration_spec.rb +357 -0
  113. data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
  114. data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
  115. data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
  116. data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
  117. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
  118. data/spec/lib/capistrano/dsl/paths_spec.rb +228 -0
  119. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +108 -0
  120. data/spec/lib/capistrano/dsl_spec.rb +125 -0
  121. data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
  122. data/spec/lib/capistrano/plugin_spec.rb +84 -0
  123. data/spec/lib/capistrano/scm/git_spec.rb +194 -0
  124. data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
  125. data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
  126. data/spec/lib/capistrano/scm_spec.rb +103 -0
  127. data/spec/lib/capistrano/upload_task_spec.rb +19 -0
  128. data/spec/lib/capistrano/version_validator_spec.rb +118 -0
  129. data/spec/lib/capistrano_spec.rb +7 -0
  130. data/spec/spec_helper.rb +29 -0
  131. data/spec/support/matchers.rb +5 -0
  132. data/spec/support/tasks/database.rake +11 -0
  133. data/spec/support/tasks/fail.rake +8 -0
  134. data/spec/support/tasks/failed.rake +5 -0
  135. data/spec/support/tasks/plugin.rake +6 -0
  136. data/spec/support/tasks/root.rake +11 -0
  137. data/spec/support/test_app.rb +205 -0
  138. metadata +234 -208
  139. data/.rvmrc +0 -1
  140. data/CHANGELOG +0 -954
  141. data/README.mdown +0 -76
  142. data/lib/capistrano/callback.rb +0 -45
  143. data/lib/capistrano/cli/execute.rb +0 -85
  144. data/lib/capistrano/cli/help.rb +0 -125
  145. data/lib/capistrano/cli/help.txt +0 -81
  146. data/lib/capistrano/cli/options.rb +0 -243
  147. data/lib/capistrano/cli/ui.rb +0 -40
  148. data/lib/capistrano/cli.rb +0 -47
  149. data/lib/capistrano/command.rb +0 -286
  150. data/lib/capistrano/configuration/actions/file_transfer.rb +0 -51
  151. data/lib/capistrano/configuration/actions/inspect.rb +0 -46
  152. data/lib/capistrano/configuration/actions/invocation.rb +0 -298
  153. data/lib/capistrano/configuration/callbacks.rb +0 -148
  154. data/lib/capistrano/configuration/connections.rb +0 -230
  155. data/lib/capistrano/configuration/execution.rb +0 -143
  156. data/lib/capistrano/configuration/loading.rb +0 -197
  157. data/lib/capistrano/configuration/namespaces.rb +0 -197
  158. data/lib/capistrano/configuration/roles.rb +0 -73
  159. data/lib/capistrano/errors.rb +0 -19
  160. data/lib/capistrano/ext/string.rb +0 -5
  161. data/lib/capistrano/extensions.rb +0 -57
  162. data/lib/capistrano/logger.rb +0 -59
  163. data/lib/capistrano/processable.rb +0 -53
  164. data/lib/capistrano/recipes/compat.rb +0 -32
  165. data/lib/capistrano/recipes/deploy/assets.rb +0 -57
  166. data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
  167. data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -54
  168. data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -111
  169. data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
  170. data/lib/capistrano/recipes/deploy/scm/base.rb +0 -196
  171. data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
  172. data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -153
  173. data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -96
  174. data/lib/capistrano/recipes/deploy/scm/git.rb +0 -282
  175. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -137
  176. data/lib/capistrano/recipes/deploy/scm/none.rb +0 -44
  177. data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -138
  178. data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -121
  179. data/lib/capistrano/recipes/deploy/scm.rb +0 -19
  180. data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -88
  181. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
  182. data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -224
  183. data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
  184. data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
  185. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -57
  186. data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
  187. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  188. data/lib/capistrano/recipes/deploy.rb +0 -568
  189. data/lib/capistrano/recipes/standard.rb +0 -37
  190. data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
  191. data/lib/capistrano/role.rb +0 -102
  192. data/lib/capistrano/server_definition.rb +0 -56
  193. data/lib/capistrano/shell.rb +0 -260
  194. data/lib/capistrano/ssh.rb +0 -101
  195. data/lib/capistrano/task_definition.rb +0 -75
  196. data/lib/capistrano/transfer.rb +0 -216
  197. data/rvmrc.sample +0 -1
  198. data/test/cli/execute_test.rb +0 -132
  199. data/test/cli/help_test.rb +0 -165
  200. data/test/cli/options_test.rb +0 -329
  201. data/test/cli/ui_test.rb +0 -28
  202. data/test/cli_test.rb +0 -17
  203. data/test/command_test.rb +0 -289
  204. data/test/configuration/actions/file_transfer_test.rb +0 -61
  205. data/test/configuration/actions/inspect_test.rb +0 -65
  206. data/test/configuration/actions/invocation_test.rb +0 -247
  207. data/test/configuration/callbacks_test.rb +0 -220
  208. data/test/configuration/connections_test.rb +0 -420
  209. data/test/configuration/execution_test.rb +0 -175
  210. data/test/configuration/loading_test.rb +0 -132
  211. data/test/configuration/namespace_dsl_test.rb +0 -311
  212. data/test/configuration/roles_test.rb +0 -144
  213. data/test/configuration/servers_test.rb +0 -183
  214. data/test/configuration/variables_test.rb +0 -190
  215. data/test/configuration_test.rb +0 -88
  216. data/test/deploy/local_dependency_test.rb +0 -76
  217. data/test/deploy/remote_dependency_test.rb +0 -135
  218. data/test/deploy/scm/accurev_test.rb +0 -23
  219. data/test/deploy/scm/base_test.rb +0 -55
  220. data/test/deploy/scm/bzr_test.rb +0 -51
  221. data/test/deploy/scm/darcs_test.rb +0 -37
  222. data/test/deploy/scm/git_test.rb +0 -184
  223. data/test/deploy/scm/mercurial_test.rb +0 -134
  224. data/test/deploy/scm/none_test.rb +0 -35
  225. data/test/deploy/scm/subversion_test.rb +0 -32
  226. data/test/deploy/strategy/copy_test.rb +0 -321
  227. data/test/extensions_test.rb +0 -69
  228. data/test/fixtures/cli_integration.rb +0 -5
  229. data/test/fixtures/config.rb +0 -5
  230. data/test/fixtures/custom.rb +0 -3
  231. data/test/logger_test.rb +0 -123
  232. data/test/recipes_test.rb +0 -25
  233. data/test/role_test.rb +0 -11
  234. data/test/server_definition_test.rb +0 -121
  235. data/test/shell_test.rb +0 -90
  236. data/test/ssh_test.rb +0 -113
  237. data/test/task_definition_test.rb +0 -116
  238. data/test/transfer_test.rb +0 -160
  239. data/test/utils.rb +0 -37
@@ -1,420 +0,0 @@
1
- require "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
- Net::SSH.stubs(:configuration_for).returns({})
34
- @ssh_options = {
35
- :user => "user",
36
- :port => 8080,
37
- :password => "g00b3r",
38
- :ssh_options => { :debug => :verbose }
39
- }
40
- end
41
-
42
- def test_initialize_should_initialize_collections_and_call_original_initialize
43
- assert @config.original_initialize_called
44
- assert @config.sessions.empty?
45
- end
46
-
47
- def test_connection_factory_should_return_default_connection_factory_instance
48
- factory = @config.connection_factory
49
- assert_instance_of Capistrano::Configuration::Connections::DefaultConnectionFactory, factory
50
- end
51
-
52
- def test_connection_factory_instance_should_be_cached
53
- assert_same @config.connection_factory, @config.connection_factory
54
- end
55
-
56
- def test_default_connection_factory_honors_config_options
57
- server = server("capistrano")
58
- Capistrano::SSH.expects(:connect).with(server, @config).returns(:session)
59
- assert_equal :session, @config.connection_factory.connect_to(server)
60
- end
61
-
62
- def test_should_connect_through_gateway_if_gateway_variable_is_set
63
- @config.values[:gateway] = "j@gateway"
64
- Net::SSH::Gateway.expects(:new).with("gateway", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
65
- assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
66
- end
67
-
68
- def test_connection_factory_as_gateway_should_honor_config_options
69
- @config.values[:gateway] = "gateway"
70
- @config.values.update(@ssh_options)
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
- assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
73
- end
74
-
75
- def test_connection_factory_as_gateway_should_chain_gateways_if_gateway_variable_is_an_array
76
- @config.values[:gateway] = ["j@gateway1", "k@gateway2"]
77
- gateway1 = mock
78
- Net::SSH::Gateway.expects(:new).with("gateway1", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(gateway1)
79
- gateway1.expects(:open).returns(65535)
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
- assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
82
- end
83
-
84
- def test_connection_factory_as_gateway_should_chain_gateways_if_gateway_variable_is_a_hash
85
- @config.values[:gateway] = { ["j@gateway1", "k@gateway2"] => :default }
86
- gateway1 = mock
87
- Net::SSH::Gateway.expects(:new).with("gateway1", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(gateway1)
88
- gateway1.expects(:open).returns(65535)
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
- assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
91
- end
92
-
93
- def test_connection_factory_as_gateway_should_share_gateway_between_connections
94
- @config.values[:gateway] = "j@gateway"
95
- Net::SSH::Gateway.expects(:new).once.with("gateway", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
96
- Capistrano::SSH.stubs(:connect).returns(stub_everything)
97
- assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
98
- @config.establish_connections_to(server("capistrano"))
99
- @config.establish_connections_to(server("another"))
100
- end
101
-
102
- def test_connection_factory_as_gateway_should_share_gateway_between_like_connections_if_gateway_variable_is_a_hash
103
- @config.values[:gateway] = { "j@gateway" => [ "capistrano", "another"] }
104
- Net::SSH::Gateway.expects(:new).once.with("gateway", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
105
- Capistrano::SSH.stubs(:connect).returns(stub_everything)
106
- assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
107
- @config.establish_connections_to(server("capistrano"))
108
- @config.establish_connections_to(server("another"))
109
- end
110
-
111
- def test_connection_factory_as_gateways_should_not_share_gateway_between_unlike_connections_if_gateway_variable_is_a_hash
112
- @config.values[:gateway] = { "j@gateway" => [ "capistrano", "another"], "k@gateway2" => "yafhost" }
113
- Net::SSH::Gateway.expects(:new).once.with("gateway", "j", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
114
- Net::SSH::Gateway.expects(:new).once.with("gateway2", "k", :password => nil, :auth_methods => %w(publickey hostbased), :config => false).returns(stub_everything)
115
- Capistrano::SSH.stubs(:connect).returns(stub_everything)
116
- assert_instance_of Capistrano::Configuration::Connections::GatewayConnectionFactory, @config.connection_factory
117
- @config.establish_connections_to(server("capistrano"))
118
- @config.establish_connections_to(server("another"))
119
- @config.establish_connections_to(server("yafhost"))
120
- end
121
-
122
- def test_establish_connections_to_should_accept_a_single_nonarray_parameter
123
- Capistrano::SSH.expects(:connect).with { |s,| s.host == "capistrano" }.returns(:success)
124
- assert @config.sessions.empty?
125
- @config.establish_connections_to(server("capistrano"))
126
- assert_equal ["capistrano"], @config.sessions.keys.map(&:host)
127
- end
128
-
129
- def test_establish_connections_to_should_accept_an_array
130
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
131
- assert @config.sessions.empty?
132
- @config.establish_connections_to(%w(cap1 cap2 cap3).map { |s| server(s) })
133
- assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map(&:host)
134
- end
135
-
136
- def test_establish_connections_to_should_not_attempt_to_reestablish_existing_connections
137
- Capistrano::SSH.expects(:connect).times(2).returns(:success)
138
- @config.sessions[server("cap1")] = :ok
139
- @config.establish_connections_to(%w(cap1 cap2 cap3).map { |s| server(s) })
140
- assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map(&:host)
141
- end
142
-
143
- def test_establish_connections_to_should_raise_one_connection_error_on_failure
144
- Capistrano::SSH.expects(:connect).times(2).raises(Exception)
145
- assert_raises(Capistrano::ConnectionError) {
146
- @config.establish_connections_to(%w(cap1 cap2).map { |s| server(s) })
147
- }
148
- end
149
-
150
- def test_connection_error_should_include_accessor_with_host_array
151
- Capistrano::SSH.expects(:connect).times(2).raises(Exception)
152
- begin
153
- @config.establish_connections_to(%w(cap1 cap2).map { |s| server(s) })
154
- flunk "expected an exception to be raised"
155
- rescue Capistrano::ConnectionError => e
156
- assert e.respond_to?(:hosts)
157
- assert_equal %w(cap1 cap2), e.hosts.map { |h| h.to_s }.sort
158
- end
159
- end
160
-
161
- def test_connection_error_should_only_include_failed_hosts
162
- Capistrano::SSH.expects(:connect).with(server('cap1'), anything).raises(Exception)
163
- Capistrano::SSH.expects(:connect).with(server('cap2'), anything).returns(:success)
164
-
165
- begin
166
- @config.establish_connections_to(%w(cap1 cap2).map { |s| server(s) })
167
- flunk "expected an exception to be raised"
168
- rescue Capistrano::ConnectionError => e
169
- assert_equal %w(cap1), e.hosts.map { |h| h.to_s }
170
- end
171
- end
172
-
173
- def test_execute_on_servers_should_require_a_block
174
- assert_raises(ArgumentError) { @config.execute_on_servers }
175
- end
176
-
177
- def test_execute_on_servers_without_current_task_should_call_find_servers
178
- list = [server("first"), server("second")]
179
- @config.expects(:find_servers).with(:a => :b, :c => :d).returns(list)
180
- @config.expects(:establish_connections_to).with(list).returns(:done)
181
- @config.execute_on_servers(:a => :b, :c => :d) do |result|
182
- assert_equal list, result
183
- end
184
- end
185
-
186
- def test_execute_on_servers_without_current_task_should_raise_error_if_no_matching_servers
187
- @config.expects(:find_servers).with(:a => :b, :c => :d).returns([])
188
- assert_raises(Capistrano::NoMatchingServersError) { @config.execute_on_servers(:a => :b, :c => :d) { |list| } }
189
- end
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
-
196
- def test_execute_on_servers_should_raise_an_error_if_the_current_task_has_no_matching_servers_by_default
197
- @config.current_task = mock_task
198
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([])
199
- assert_raises(Capistrano::NoMatchingServersError) do
200
- @config.execute_on_servers do
201
- flunk "should not get here"
202
- end
203
- end
204
- end
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
-
226
- def test_execute_on_servers_should_determine_server_list_from_active_task
227
- assert @config.sessions.empty?
228
- @config.current_task = mock_task
229
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2"), server("cap3")])
230
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
231
- @config.execute_on_servers {}
232
- assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map { |s| s.host }
233
- end
234
-
235
- def test_execute_on_servers_should_yield_server_list_to_block
236
- assert @config.sessions.empty?
237
- @config.current_task = mock_task
238
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2"), server("cap3")])
239
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
240
- block_called = false
241
- @config.execute_on_servers do |servers|
242
- block_called = true
243
- assert servers.detect { |s| s.host == "cap1" }
244
- assert servers.detect { |s| s.host == "cap2" }
245
- assert servers.detect { |s| s.host == "cap3" }
246
- assert servers.all? { |s| @config.sessions[s] }
247
- end
248
- assert block_called
249
- end
250
-
251
- def test_execute_on_servers_with_once_option_should_establish_connection_to_and_yield_only_the_first_server
252
- assert @config.sessions.empty?
253
- @config.current_task = mock_task
254
- @config.expects(:find_servers_for_task).with(@config.current_task, :once => true).returns([server("cap1"), server("cap2"), server("cap3")])
255
- Capistrano::SSH.expects(:connect).returns(:success)
256
- block_called = false
257
- @config.execute_on_servers(:once => true) do |servers|
258
- block_called = true
259
- assert_equal %w(cap1), servers.map { |s| s.host }
260
- end
261
- assert block_called
262
- assert_equal %w(cap1), @config.sessions.keys.sort.map { |s| s.host }
263
- end
264
-
265
- def test_execute_servers_should_raise_connection_error_on_failure_by_default
266
- @config.current_task = mock_task
267
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1")])
268
- Capistrano::SSH.expects(:connect).raises(Exception)
269
- assert_raises(Capistrano::ConnectionError) do
270
- @config.execute_on_servers do
271
- flunk "expected an exception to be raised"
272
- end
273
- end
274
- end
275
-
276
- def test_execute_servers_should_not_raise_connection_error_on_failure_with_on_errors_continue
277
- @config.current_task = mock_task(:on_error => :continue)
278
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2")])
279
- Capistrano::SSH.expects(:connect).with(server('cap1'), anything).raises(Exception)
280
- Capistrano::SSH.expects(:connect).with(server('cap2'), anything).returns(:success)
281
- assert_nothing_raised {
282
- @config.execute_on_servers do |servers|
283
- assert_equal %w(cap2), servers.map { |s| s.host }
284
- end
285
- }
286
- end
287
-
288
- def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_connection_errors_with_on_errors_continue
289
- list = [server("cap1"), server("cap2")]
290
- @config.current_task = mock_task(:on_error => :continue)
291
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns(list)
292
- Capistrano::SSH.expects(:connect).with(server('cap1'), anything).raises(Exception)
293
- Capistrano::SSH.expects(:connect).with(server('cap2'), anything).returns(:success)
294
- @config.execute_on_servers do |servers|
295
- assert_equal %w(cap2), servers.map { |s| s.host }
296
- end
297
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns(list)
298
- @config.execute_on_servers do |servers|
299
- assert_equal %w(cap2), servers.map { |s| s.host }
300
- end
301
- end
302
-
303
- def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_command_errors_with_on_errors_continue
304
- cap1 = server("cap1")
305
- cap2 = server("cap2")
306
- @config.current_task = mock_task(:on_error => :continue)
307
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
308
- Capistrano::SSH.expects(:connect).times(2).returns(:success)
309
- @config.execute_on_servers do |servers|
310
- error = Capistrano::CommandError.new
311
- error.hosts = [cap1]
312
- raise error
313
- end
314
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
315
- @config.execute_on_servers do |servers|
316
- assert_equal %w(cap2), servers.map { |s| s.host }
317
- end
318
- end
319
-
320
- def test_execute_on_servers_should_not_try_to_connect_to_hosts_with_transfer_errors_with_on_errors_continue
321
- cap1 = server("cap1")
322
- cap2 = server("cap2")
323
- @config.current_task = mock_task(:on_error => :continue)
324
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
325
- Capistrano::SSH.expects(:connect).times(2).returns(:success)
326
- @config.execute_on_servers do |servers|
327
- error = Capistrano::TransferError.new
328
- error.hosts = [cap1]
329
- raise error
330
- end
331
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
332
- @config.execute_on_servers do |servers|
333
- assert_equal %w(cap2), servers.map { |s| s.host }
334
- end
335
- end
336
-
337
- def test_connect_should_establish_connections_to_all_servers_in_scope
338
- assert @config.sessions.empty?
339
- @config.current_task = mock_task
340
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([server("cap1"), server("cap2"), server("cap3")])
341
- Capistrano::SSH.expects(:connect).times(3).returns(:success)
342
- @config.connect!
343
- assert_equal %w(cap1 cap2 cap3), @config.sessions.keys.sort.map { |s| s.host }
344
- end
345
-
346
- def test_execute_on_servers_should_only_run_on_tasks_max_hosts_hosts_at_once
347
- cap1 = server("cap1")
348
- cap2 = server("cap2")
349
- connection1 = mock()
350
- connection2 = mock()
351
- connection1.expects(:close)
352
- connection2.expects(:close)
353
- @config.current_task = mock_task(:max_hosts => 1)
354
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
355
- Capistrano::SSH.expects(:connect).times(2).returns(connection1).then.returns(connection2)
356
- block_called = 0
357
- @config.execute_on_servers do |servers|
358
- block_called += 1
359
- assert_equal 1, servers.size
360
- end
361
- assert_equal 2, block_called
362
- end
363
-
364
- def test_execute_on_servers_should_only_run_on_max_hosts_hosts_at_once
365
- cap1 = server("cap1")
366
- cap2 = server("cap2")
367
- connection1 = mock()
368
- connection2 = mock()
369
- connection1.expects(:close)
370
- connection2.expects(:close)
371
- @config.current_task = mock_task(:max_hosts => 1)
372
- @config.expects(:find_servers_for_task).with(@config.current_task, {}).returns([cap1, cap2])
373
- Capistrano::SSH.expects(:connect).times(2).returns(connection1).then.returns(connection2)
374
- block_called = 0
375
- @config.execute_on_servers do |servers|
376
- block_called += 1
377
- assert_equal 1, servers.size
378
- end
379
- assert_equal 2, block_called
380
- end
381
-
382
- def test_execute_on_servers_should_cope_with_already_dropped_connections_when_attempting_to_close_them
383
- cap1 = server("cap1")
384
- cap2 = server("cap2")
385
- connection1 = mock()
386
- connection2 = mock()
387
- connection3 = mock()
388
- connection4 = mock()
389
- connection1.expects(:close).raises(IOError)
390
- connection2.expects(:close)
391
- connection3.expects(:close)
392
- connection4.expects(:close)
393
- @config.current_task = mock_task(:max_hosts => 1)
394
- @config.expects(:find_servers_for_task).times(2).with(@config.current_task, {}).returns([cap1, cap2])
395
- Capistrano::SSH.expects(:connect).times(4).returns(connection1).then.returns(connection2).then.returns(connection3).then.returns(connection4)
396
- @config.execute_on_servers {}
397
- @config.execute_on_servers {}
398
- end
399
-
400
- def test_connect_should_honor_once_option
401
- assert @config.sessions.empty?
402
- @config.current_task = mock_task
403
- @config.expects(:find_servers_for_task).with(@config.current_task, :once => true).returns([server("cap1"), server("cap2"), server("cap3")])
404
- Capistrano::SSH.expects(:connect).returns(:success)
405
- @config.connect! :once => true
406
- assert_equal %w(cap1), @config.sessions.keys.sort.map { |s| s.host }
407
- end
408
-
409
- private
410
-
411
- def mock_task(options={})
412
- continue_on_error = options[:on_error] == :continue
413
- stub("task",
414
- :fully_qualified_name => "name",
415
- :options => options,
416
- :continue_on_error? => continue_on_error,
417
- :max_hosts => options[:max_hosts]
418
- )
419
- end
420
- end
@@ -1,175 +0,0 @@
1
- require "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_on_rollback_called_twice_should_result_in_last_rollback_block_being_effective
120
- aaa = new_task(@config, :aaa) do
121
- transaction do
122
- on_rollback { (state[:rollback] ||= []) << :first }
123
- on_rollback { (state[:rollback] ||= []) << :second }
124
- raise "boom"
125
- end
126
- end
127
-
128
- assert_raises(RuntimeError) do
129
- @config.execute_task(aaa)
130
- end
131
-
132
- assert_equal [:second], @config.state[:rollback]
133
- end
134
-
135
- def test_find_and_execute_task_should_raise_error_when_task_cannot_be_found
136
- @config.expects(:find_task).with("path:to:task").returns(nil)
137
- assert_raises(Capistrano::NoSuchTaskError) { @config.find_and_execute_task("path:to:task") }
138
- end
139
-
140
- def test_find_and_execute_task_should_execute_task_when_task_is_found
141
- @config.expects(:find_task).with("path:to:task").returns(:found)
142
- @config.expects(:execute_task).with(:found)
143
- assert_nothing_raised { @config.find_and_execute_task("path:to:task") }
144
- end
145
-
146
- def test_find_and_execute_task_with_before_option_should_trigger_callback
147
- @config.expects(:find_task).with("path:to:task").returns(:found)
148
- @config.expects(:trigger).with(:incoming, :found)
149
- @config.expects(:execute_task).with(:found)
150
- @config.find_and_execute_task("path:to:task", :before => :incoming)
151
- end
152
-
153
- def test_find_and_execute_task_with_after_option_should_trigger_callback
154
- @config.expects(:find_task).with("path:to:task").returns(:found)
155
- @config.expects(:trigger).with(:outgoing, :found)
156
- @config.expects(:execute_task).with(:found)
157
- @config.find_and_execute_task("path:to:task", :after => :outgoing)
158
- end
159
-
160
- private
161
-
162
- def stack_inspector
163
- Proc.new do
164
- (state[:trail] ||= []) << current_task.fully_qualified_name
165
- data = state[current_task.name] = {}
166
- data[:stack] = task_call_frames.map { |frame| frame.task.fully_qualified_name }
167
- data[:history] = rollback_requests && rollback_requests.map { |frame| frame.task.fully_qualified_name }
168
- end
169
- end
170
-
171
- def new_task(namespace, name, options={}, &block)
172
- block ||= stack_inspector
173
- namespace.tasks[name] = Capistrano::TaskDefinition.new(name, namespace, &block)
174
- end
175
- end