capistrano 2.8.0 → 3.19.0

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