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
@@ -0,0 +1,357 @@
1
+ require "spec_helper"
2
+
3
+ module Capistrano
4
+ describe Configuration do
5
+ let(:config) { Configuration.new }
6
+ let(:servers) { stub }
7
+
8
+ describe ".new" do
9
+ it "accepts initial hash" do
10
+ configuration = described_class.new(custom: "value")
11
+ expect(configuration.fetch(:custom)).to eq("value")
12
+ end
13
+ end
14
+
15
+ describe ".env" do
16
+ it "is a global accessor to a single instance" do
17
+ Configuration.env.set(:test, true)
18
+ expect(Configuration.env.fetch(:test)).to be_truthy
19
+ end
20
+ end
21
+
22
+ describe ".reset!" do
23
+ it "blows away the existing `env` and creates a new one" do
24
+ old_env = Configuration.env
25
+ Configuration.reset!
26
+ expect(Configuration.env).not_to be old_env
27
+ end
28
+ end
29
+
30
+ describe "roles" do
31
+ context "adding a role" do
32
+ subject { config.role(:app, %w{server1 server2}) }
33
+
34
+ before do
35
+ Configuration::Servers.expects(:new).returns(servers)
36
+ servers.expects(:add_role).with(:app, %w{server1 server2}, {})
37
+ end
38
+
39
+ it "adds the role" do
40
+ expect(subject)
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "setting and fetching" do
46
+ subject { config.fetch(:key, :default) }
47
+
48
+ context "set" do
49
+ it "sets by value" do
50
+ config.set(:key, :value)
51
+ expect(subject).to eq :value
52
+ end
53
+
54
+ it "sets by block" do
55
+ config.set(:key) { :value }
56
+ expect(subject).to eq :value
57
+ end
58
+
59
+ it "raises an exception when given both a value and block" do
60
+ expect { config.set(:key, :value) { :value } }.to raise_error(Capistrano::ValidationError)
61
+ end
62
+ end
63
+
64
+ context "set_if_empty" do
65
+ it "sets by value when none is present" do
66
+ config.set_if_empty(:key, :value)
67
+ expect(subject).to eq :value
68
+ end
69
+
70
+ it "sets by block when none is present" do
71
+ config.set_if_empty(:key) { :value }
72
+ expect(subject).to eq :value
73
+ end
74
+
75
+ it "does not overwrite existing values" do
76
+ config.set(:key, :value)
77
+ config.set_if_empty(:key, :update)
78
+ config.set_if_empty(:key) { :update }
79
+ expect(subject).to eq :value
80
+ end
81
+ end
82
+
83
+ context "value is not set" do
84
+ it "returns the default value" do
85
+ expect(subject).to eq :default
86
+ end
87
+ end
88
+
89
+ context "value is a proc" do
90
+ subject { config.fetch(:key, proc { :proc }) }
91
+ it "calls the proc" do
92
+ expect(subject).to eq :proc
93
+ end
94
+ end
95
+
96
+ context "value is a lambda" do
97
+ subject { config.fetch(:key, -> { :lambda }) }
98
+ it "calls the lambda" do
99
+ expect(subject).to eq :lambda
100
+ end
101
+ end
102
+
103
+ context "value inside proc inside a proc" do
104
+ subject { config.fetch(:key, proc { proc { "some value" } }) }
105
+ it "calls all procs and lambdas" do
106
+ expect(subject).to eq "some value"
107
+ end
108
+ end
109
+
110
+ context "value inside lambda inside a lambda" do
111
+ subject { config.fetch(:key, -> { -> { "some value" } }) }
112
+ it "calls all procs and lambdas" do
113
+ expect(subject).to eq "some value"
114
+ end
115
+ end
116
+
117
+ context "value inside lambda inside a proc" do
118
+ subject { config.fetch(:key, proc { -> { "some value" } }) }
119
+ it "calls all procs and lambdas" do
120
+ expect(subject).to eq "some value"
121
+ end
122
+ end
123
+
124
+ context "value inside proc inside a lambda" do
125
+ subject { config.fetch(:key, -> { proc { "some value" } }) }
126
+ it "calls all procs and lambdas" do
127
+ expect(subject).to eq "some value"
128
+ end
129
+ end
130
+
131
+ context "lambda with parameters" do
132
+ subject { config.fetch(:key, ->(c) { c }).call(42) }
133
+ it "is returned as a lambda" do
134
+ expect(subject).to eq 42
135
+ end
136
+ end
137
+
138
+ context "block is passed to fetch" do
139
+ subject { config.fetch(:key, :default) { raise "we need this!" } }
140
+
141
+ it "returns the block value" do
142
+ expect { subject }.to raise_error(RuntimeError)
143
+ end
144
+ end
145
+
146
+ context "validations" do
147
+ before do
148
+ config.validate :key do |_, value|
149
+ raise Capistrano::ValidationError unless value.length > 3
150
+ end
151
+ end
152
+
153
+ it "validates string without error" do
154
+ config.set(:key, "longer_value")
155
+ end
156
+
157
+ it "validates block without error" do
158
+ config.set(:key) { "longer_value" }
159
+ expect(config.fetch(:key)).to eq "longer_value"
160
+ end
161
+
162
+ it "validates lambda without error" do
163
+ config.set :key, -> { "longer_value" }
164
+ expect(config.fetch(:key)).to eq "longer_value"
165
+ end
166
+
167
+ it "raises an exception on invalid string" do
168
+ expect { config.set(:key, "sho") }.to raise_error(Capistrano::ValidationError)
169
+ end
170
+
171
+ it "raises an exception on invalid string provided by block" do
172
+ config.set(:key) { "sho" }
173
+ expect { config.fetch(:key) }.to raise_error(Capistrano::ValidationError)
174
+ end
175
+
176
+ it "raises an exception on invalid string provided by lambda" do
177
+ config.set :key, -> { "sho" }
178
+ expect { config.fetch(:key) }.to raise_error(Capistrano::ValidationError)
179
+ end
180
+ end
181
+
182
+ context "appending" do
183
+ subject { config.append(:linked_dirs, "vendor/bundle", "tmp") }
184
+
185
+ it "returns appended value" do
186
+ expect(subject).to eq ["vendor/bundle", "tmp"]
187
+ end
188
+
189
+ context "on non-array variable" do
190
+ before { config.set(:linked_dirs, "string") }
191
+ subject { config.append(:linked_dirs, "vendor/bundle") }
192
+
193
+ it "returns appended value" do
194
+ expect(subject).to eq ["string", "vendor/bundle"]
195
+ end
196
+ end
197
+ end
198
+
199
+ context "removing" do
200
+ before :each do
201
+ config.set(:linked_dirs, ["vendor/bundle", "tmp"])
202
+ end
203
+
204
+ subject { config.remove(:linked_dirs, "vendor/bundle") }
205
+
206
+ it "returns without removed value" do
207
+ expect(subject).to eq ["tmp"]
208
+ end
209
+
210
+ context "on non-array variable" do
211
+ before { config.set(:linked_dirs, "string") }
212
+
213
+ context "when removing same value" do
214
+ subject { config.remove(:linked_dirs, "string") }
215
+
216
+ it "returns without removed value" do
217
+ expect(subject).to eq []
218
+ end
219
+ end
220
+
221
+ context "when removing different value" do
222
+ subject { config.remove(:linked_dirs, "othervalue") }
223
+
224
+ it "returns without removed value" do
225
+ expect(subject).to eq ["string"]
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
231
+
232
+ describe "keys" do
233
+ subject { config.keys }
234
+
235
+ before do
236
+ config.set(:key1, :value1)
237
+ config.set(:key2, :value2)
238
+ end
239
+
240
+ it "returns all set keys" do
241
+ expect(subject).to match_array %i(key1 key2)
242
+ end
243
+ end
244
+
245
+ describe "deleting" do
246
+ before do
247
+ config.set(:key, :value)
248
+ end
249
+
250
+ it "deletes the value" do
251
+ config.delete(:key)
252
+ expect(config.fetch(:key)).to be_nil
253
+ end
254
+ end
255
+
256
+ describe "asking" do
257
+ let(:question) { stub }
258
+ let(:options) { {} }
259
+
260
+ before do
261
+ Configuration::Question.expects(:new).with(:branch, :default, options)
262
+ .returns(question)
263
+ end
264
+
265
+ it "prompts for the value when fetching" do
266
+ config.ask(:branch, :default, options)
267
+ expect(config.fetch(:branch)).to eq question
268
+ end
269
+ end
270
+
271
+ describe "setting the backend" do
272
+ it "by default, is SSHKit" do
273
+ expect(config.backend).to eq SSHKit
274
+ end
275
+
276
+ it "can be set to another class" do
277
+ config.backend = :test
278
+ expect(config.backend).to eq :test
279
+ end
280
+
281
+ describe "ssh_options for Netssh" do
282
+ it "merges them with the :ssh_options variable" do
283
+ config.set :format, :pretty
284
+ config.set :log_level, :debug
285
+ config.set :ssh_options, user: "albert"
286
+ SSHKit::Backend::Netssh.configure { |ssh| ssh.ssh_options = { password: "einstein" } }
287
+ config.configure_backend
288
+
289
+ expect(
290
+ config.backend.config.backend.config.ssh_options
291
+ ).to include(user: "albert", password: "einstein")
292
+ end
293
+ end
294
+ end
295
+
296
+ describe "dry_run?" do
297
+ it "returns false when using default backend" do
298
+ expect(config.dry_run?).to eq(false)
299
+ end
300
+
301
+ it "returns true when using printer backend" do
302
+ config.set :sshkit_backend, SSHKit::Backend::Printer
303
+
304
+ expect(config.dry_run?).to eq(true)
305
+ end
306
+ end
307
+
308
+ describe "custom filtering" do
309
+ it "accepts a custom filter object" do
310
+ filter = Object.new
311
+ def filter.filter(servers)
312
+ servers
313
+ end
314
+ config.add_filter(filter)
315
+ end
316
+
317
+ it "accepts a custom filter as a block" do
318
+ config.add_filter { |servers| servers }
319
+ end
320
+
321
+ it "raises an error if passed a block and an object" do
322
+ filter = Object.new
323
+ def filter.filter(servers)
324
+ servers
325
+ end
326
+
327
+ expect { config.add_filter(filter) { |servers| servers } }.to raise_error(ArgumentError)
328
+ end
329
+
330
+ it "raises an error if the filter lacks a filter method" do
331
+ filter = Object.new
332
+ expect { config.add_filter(filter) }.to raise_error(TypeError)
333
+ end
334
+
335
+ it "calls the filter method of a custom filter" do
336
+ ENV.delete "ROLES"
337
+ ENV.delete "HOSTS"
338
+
339
+ servers = Configuration::Servers.new
340
+
341
+ servers.add_host("test1")
342
+ servers.add_host("test2")
343
+ servers.add_host("test3")
344
+
345
+ filtered_servers = servers.take(2)
346
+
347
+ filter = mock("custom filter")
348
+ filter.expects(:filter)
349
+ .with { |subset| subset.is_a? Configuration::Servers }
350
+ .returns(filtered_servers)
351
+
352
+ config.add_filter(filter)
353
+ expect(config.filter(servers)).to eq(filtered_servers)
354
+ end
355
+ end
356
+ end
357
+ end
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+ require "capistrano/doctor/environment_doctor"
3
+
4
+ module Capistrano
5
+ module Doctor
6
+ describe EnvironmentDoctor do
7
+ let(:doc) { EnvironmentDoctor.new }
8
+
9
+ it "prints using 4-space indentation" do
10
+ expect { doc.call }.to output(/^ {4}/).to_stdout
11
+ end
12
+
13
+ it "prints the Ruby version" do
14
+ expect { doc.call }.to\
15
+ output(/#{Regexp.quote(RUBY_DESCRIPTION)}/).to_stdout
16
+ end
17
+
18
+ it "prints the Rubygems version" do
19
+ expect { doc.call }.to output(/#{Regexp.quote(Gem::VERSION)}/).to_stdout
20
+ end
21
+
22
+ describe "Rake" do
23
+ before do
24
+ load File.expand_path("../../../../../lib/capistrano/doctor.rb",
25
+ __FILE__)
26
+ end
27
+
28
+ after do
29
+ Rake::Task.clear
30
+ end
31
+
32
+ it "has an doctor:environment task that calls EnvironmentDoctor", capture_io: true do
33
+ EnvironmentDoctor.any_instance.expects(:call)
34
+ Rake::Task["doctor:environment"].invoke
35
+ end
36
+
37
+ it "has a doctor task that depends on doctor:environment" do
38
+ expect(Rake::Task["doctor"].prerequisites).to \
39
+ include("doctor:environment")
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,67 @@
1
+ require "spec_helper"
2
+ require "capistrano/doctor/gems_doctor"
3
+ require "airbrussh/version"
4
+ require "sshkit/version"
5
+ require "net/ssh/version"
6
+
7
+ module Capistrano
8
+ module Doctor
9
+ describe GemsDoctor do
10
+ let(:doc) { GemsDoctor.new }
11
+
12
+ it "prints using 4-space indentation" do
13
+ expect { doc.call }.to output(/^ {4}/).to_stdout
14
+ end
15
+
16
+ it "prints the Capistrano version" do
17
+ expect { doc.call }.to\
18
+ output(/capistrano\s+#{Regexp.quote(Capistrano::VERSION)}/).to_stdout
19
+ end
20
+
21
+ it "prints the Rake version" do
22
+ expect { doc.call }.to\
23
+ output(/rake\s+#{Regexp.quote(Rake::VERSION)}/).to_stdout
24
+ end
25
+
26
+ it "prints the SSHKit version" do
27
+ expect { doc.call }.to\
28
+ output(/sshkit\s+#{Regexp.quote(SSHKit::VERSION)}/).to_stdout
29
+ end
30
+
31
+ it "prints the Airbrussh version" do
32
+ expect { doc.call }.to\
33
+ output(/airbrussh\s+#{Regexp.quote(Airbrussh::VERSION)}/).to_stdout
34
+ end
35
+
36
+ it "prints the net-ssh version" do
37
+ expect { doc.call }.to\
38
+ output(/net-ssh\s+#{Regexp.quote(Net::SSH::Version::STRING)}/).to_stdout
39
+ end
40
+
41
+ it "warns that new version is available" do
42
+ Gem.stubs(:latest_version_for).returns(Gem::Version.new("99.0.0"))
43
+ expect { doc.call }.to output(/\(update available\)/).to_stdout
44
+ end
45
+
46
+ describe "Rake" do
47
+ before do
48
+ load File.expand_path("../../../../../lib/capistrano/doctor.rb",
49
+ __FILE__)
50
+ end
51
+
52
+ after do
53
+ Rake::Task.clear
54
+ end
55
+
56
+ it "has an doctor:gems task that calls GemsDoctor", capture_io: true do
57
+ GemsDoctor.any_instance.expects(:call)
58
+ Rake::Task["doctor:gems"].invoke
59
+ end
60
+
61
+ it "has a doctor task that depends on doctor:gems" do
62
+ expect(Rake::Task["doctor"].prerequisites).to include("doctor:gems")
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+ require "capistrano/doctor/output_helpers"
3
+
4
+ module Capistrano
5
+ module Doctor
6
+ describe OutputHelpers do
7
+ include OutputHelpers
8
+
9
+ # Force color for the purpose of these tests
10
+ before { ENV.stubs(:[]).with("SSHKIT_COLOR").returns("1") }
11
+
12
+ it "prints titles in blue with newlines and without indentation" do
13
+ expect { title("Hello!") }.to\
14
+ output("\e[0;34;49m\nHello!\n\e[0m\n").to_stdout
15
+ end
16
+
17
+ it "prints warnings in yellow with 4-space indentation" do
18
+ expect { warning("Yikes!") }.to\
19
+ output(" \e[0;33;49mYikes!\e[0m\n").to_stdout
20
+ end
21
+
22
+ it "overrides puts to indent 4 spaces per line" do
23
+ expect { puts("one\ntwo") }.to output(" one\n two\n").to_stdout
24
+ end
25
+
26
+ it "formats tables with indent, aligned columns and per-row color" do
27
+ data = [
28
+ ["one", ".", "1"],
29
+ ["two", "..", "2"],
30
+ ["three", "...", "3"]
31
+ ]
32
+ block = proc do |record, row|
33
+ row.yellow if record.first == "two"
34
+ row << record[0]
35
+ row << record[1]
36
+ row << record[2]
37
+ end
38
+ expected_output = <<-OUT
39
+ one . 1
40
+ \e[0;33;49mtwo .. 2\e[0m
41
+ three ... 3
42
+ OUT
43
+ expect { table(data, &block) }.to output(expected_output).to_stdout
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,86 @@
1
+ require "spec_helper"
2
+ require "capistrano/doctor/servers_doctor"
3
+
4
+ module Capistrano
5
+ module Doctor
6
+ describe ServersDoctor do
7
+ include Capistrano::DSL
8
+ let(:doc) { ServersDoctor.new }
9
+
10
+ before { Capistrano::Configuration.reset! }
11
+ after { Capistrano::Configuration.reset! }
12
+
13
+ it "prints using 4-space indentation" do
14
+ expect { doc.call }.to output(/^ {4}/).to_stdout
15
+ end
16
+
17
+ it "prints the number of defined servers" do
18
+ role :app, %w(example.com)
19
+ server "www@example.com:22"
20
+
21
+ expect { doc.call }.to output(/Servers \(2\)/).to_stdout
22
+ end
23
+
24
+ describe "prints the server's details" do
25
+ it "including username" do
26
+ server "www@example.com"
27
+ expect { doc.call }.to output(/www@example.com/).to_stdout
28
+ end
29
+
30
+ it "including port" do
31
+ server "www@example.com:22"
32
+ expect { doc.call }.to output(/www@example.com:22/).to_stdout
33
+ end
34
+
35
+ it "including roles" do
36
+ role :app, %w(example.com)
37
+ expect { doc.call }.to output(/example.com\s+\[:app\]/).to_stdout
38
+ end
39
+
40
+ it "including empty roles" do
41
+ server "example.com"
42
+ expect { doc.call }.to output(/example.com\s+\[\]/).to_stdout
43
+ end
44
+
45
+ it "including properties" do
46
+ server "example.com", roles: %w(app db), primary: true
47
+ expect { doc.call }.to \
48
+ output(/example.com\s+\[:app, :db\]\s+\{ :primary => true \}/).to_stdout
49
+ end
50
+
51
+ it "including misleading role name alert" do
52
+ server "example.com", roles: ["web app db"]
53
+ warning_msg = 'Whitespace detected in role(s) :"web app db". ' \
54
+ 'This might be a result of a mistyped "%w()" array literal'
55
+
56
+ expect { doc.call }.to output(/#{Regexp.escape(warning_msg)}/).to_stdout
57
+ end
58
+ end
59
+
60
+ it "doesn't fail for no servers" do
61
+ expect { doc.call }.to output("\nServers (0)\n \n").to_stdout
62
+ end
63
+
64
+ describe "Rake" do
65
+ before do
66
+ load File.expand_path("../../../../../lib/capistrano/doctor.rb",
67
+ __FILE__)
68
+ end
69
+
70
+ after do
71
+ Rake::Task.clear
72
+ end
73
+
74
+ it "has an doctor:servers task that calls ServersDoctor", capture_io: true do
75
+ ServersDoctor.any_instance.expects(:call)
76
+ Rake::Task["doctor:servers"].invoke
77
+ end
78
+
79
+ it "has a doctor task that depends on doctor:servers" do
80
+ expect(Rake::Task["doctor"].prerequisites).to \
81
+ include("doctor:servers")
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,89 @@
1
+ require "spec_helper"
2
+ require "capistrano/doctor/variables_doctor"
3
+
4
+ module Capistrano
5
+ module Doctor
6
+ describe VariablesDoctor do
7
+ include Capistrano::DSL
8
+
9
+ let(:doc) { VariablesDoctor.new }
10
+
11
+ before do
12
+ set :branch, "master"
13
+ set :pty, false
14
+
15
+ env.variables.untrusted! do
16
+ set :application, "my_app"
17
+ set :repo_tree, "public"
18
+ set :repo_url, ".git"
19
+ set :copy_strategy, :scp
20
+ set :custom_setting, "hello"
21
+ set "string_setting", "hello"
22
+ ask :secret
23
+ end
24
+
25
+ fetch :custom_setting
26
+ end
27
+
28
+ after { Capistrano::Configuration.reset! }
29
+
30
+ it "prints using 4-space indentation" do
31
+ expect { doc.call }.to output(/^ {4}/).to_stdout
32
+ end
33
+
34
+ it "prints variable names and values" do
35
+ expect { doc.call }.to output(/:branch\s+"master"$/).to_stdout
36
+ expect { doc.call }.to output(/:pty\s+false$/).to_stdout
37
+ expect { doc.call }.to output(/:application\s+"my_app"$/).to_stdout
38
+ expect { doc.call }.to output(/:repo_url\s+".git"$/).to_stdout
39
+ expect { doc.call }.to output(/:repo_tree\s+"public"$/).to_stdout
40
+ expect { doc.call }.to output(/:copy_strategy\s+:scp$/).to_stdout
41
+ expect { doc.call }.to output(/:custom_setting\s+"hello"$/).to_stdout
42
+ expect { doc.call }.to output(/"string_setting"\s+"hello"$/).to_stdout
43
+ end
44
+
45
+ it "prints unanswered question variable as <ask>" do
46
+ expect { doc.call }.to output(/:secret\s+<ask>$/).to_stdout
47
+ end
48
+
49
+ it "prints warning for unrecognized variable" do
50
+ expect { doc.call }.to \
51
+ output(/:copy_strategy is not a recognized Capistrano setting/)\
52
+ .to_stdout
53
+ end
54
+
55
+ it "does not print warning for unrecognized variable that is fetched" do
56
+ expect { doc.call }.not_to \
57
+ output(/:custom_setting is not a recognized Capistrano setting/)\
58
+ .to_stdout
59
+ end
60
+
61
+ it "does not print warning for whitelisted variable" do
62
+ expect { doc.call }.not_to \
63
+ output(/:repo_tree is not a recognized Capistrano setting/)\
64
+ .to_stdout
65
+ end
66
+
67
+ describe "Rake" do
68
+ before do
69
+ load File.expand_path("../../../../../lib/capistrano/doctor.rb",
70
+ __FILE__)
71
+ end
72
+
73
+ after do
74
+ Rake::Task.clear
75
+ end
76
+
77
+ it "has an doctor:variables task that calls VariablesDoctor", capture_io: true do
78
+ VariablesDoctor.any_instance.expects(:call)
79
+ Rake::Task["doctor:variables"].invoke
80
+ end
81
+
82
+ it "has a doctor task that depends on doctor:variables" do
83
+ expect(Rake::Task["doctor"].prerequisites).to \
84
+ include("doctor:variables")
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end