capistrano 1.4.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. data/CHANGELOG +140 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README +22 -14
  4. data/bin/cap +1 -8
  5. data/bin/capify +77 -0
  6. data/examples/sample.rb +10 -109
  7. data/lib/capistrano.rb +1 -0
  8. data/lib/capistrano/callback.rb +41 -0
  9. data/lib/capistrano/cli.rb +17 -317
  10. data/lib/capistrano/cli/execute.rb +82 -0
  11. data/lib/capistrano/cli/help.rb +102 -0
  12. data/lib/capistrano/cli/help.txt +53 -0
  13. data/lib/capistrano/cli/options.rb +183 -0
  14. data/lib/capistrano/cli/ui.rb +28 -0
  15. data/lib/capistrano/command.rb +62 -29
  16. data/lib/capistrano/configuration.rb +25 -226
  17. data/lib/capistrano/configuration/actions/file_transfer.rb +35 -0
  18. data/lib/capistrano/configuration/actions/inspect.rb +46 -0
  19. data/lib/capistrano/configuration/actions/invocation.rb +127 -0
  20. data/lib/capistrano/configuration/callbacks.rb +148 -0
  21. data/lib/capistrano/configuration/connections.rb +159 -0
  22. data/lib/capistrano/configuration/execution.rb +126 -0
  23. data/lib/capistrano/configuration/loading.rb +112 -0
  24. data/lib/capistrano/configuration/namespaces.rb +190 -0
  25. data/lib/capistrano/configuration/roles.rb +51 -0
  26. data/lib/capistrano/configuration/servers.rb +75 -0
  27. data/lib/capistrano/configuration/variables.rb +127 -0
  28. data/lib/capistrano/errors.rb +15 -0
  29. data/lib/capistrano/extensions.rb +27 -8
  30. data/lib/capistrano/gateway.rb +54 -29
  31. data/lib/capistrano/logger.rb +11 -11
  32. data/lib/capistrano/recipes/compat.rb +32 -0
  33. data/lib/capistrano/recipes/deploy.rb +483 -0
  34. data/lib/capistrano/recipes/deploy/dependencies.rb +44 -0
  35. data/lib/capistrano/recipes/deploy/local_dependency.rb +46 -0
  36. data/lib/capistrano/recipes/deploy/remote_dependency.rb +65 -0
  37. data/lib/capistrano/recipes/deploy/scm.rb +19 -0
  38. data/lib/capistrano/recipes/deploy/scm/base.rb +180 -0
  39. data/lib/capistrano/recipes/deploy/scm/bzr.rb +86 -0
  40. data/lib/capistrano/recipes/deploy/scm/cvs.rb +151 -0
  41. data/lib/capistrano/recipes/deploy/scm/darcs.rb +85 -0
  42. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +129 -0
  43. data/lib/capistrano/recipes/deploy/scm/perforce.rb +126 -0
  44. data/lib/capistrano/recipes/deploy/scm/subversion.rb +103 -0
  45. data/lib/capistrano/recipes/deploy/strategy.rb +19 -0
  46. data/lib/capistrano/recipes/deploy/strategy/base.rb +64 -0
  47. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +20 -0
  48. data/lib/capistrano/recipes/deploy/strategy/copy.rb +143 -0
  49. data/lib/capistrano/recipes/deploy/strategy/export.rb +20 -0
  50. data/lib/capistrano/recipes/deploy/strategy/remote.rb +52 -0
  51. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +47 -0
  52. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +53 -0
  53. data/lib/capistrano/recipes/standard.rb +26 -276
  54. data/lib/capistrano/recipes/templates/maintenance.rhtml +1 -1
  55. data/lib/capistrano/recipes/upgrade.rb +33 -0
  56. data/lib/capistrano/server_definition.rb +51 -0
  57. data/lib/capistrano/shell.rb +125 -81
  58. data/lib/capistrano/ssh.rb +80 -36
  59. data/lib/capistrano/task_definition.rb +69 -0
  60. data/lib/capistrano/upload.rb +146 -0
  61. data/lib/capistrano/version.rb +13 -17
  62. data/test/cli/execute_test.rb +132 -0
  63. data/test/cli/help_test.rb +139 -0
  64. data/test/cli/options_test.rb +226 -0
  65. data/test/cli/ui_test.rb +28 -0
  66. data/test/cli_test.rb +17 -0
  67. data/test/command_test.rb +284 -25
  68. data/test/configuration/actions/file_transfer_test.rb +40 -0
  69. data/test/configuration/actions/inspect_test.rb +62 -0
  70. data/test/configuration/actions/invocation_test.rb +195 -0
  71. data/test/configuration/callbacks_test.rb +206 -0
  72. data/test/configuration/connections_test.rb +288 -0
  73. data/test/configuration/execution_test.rb +159 -0
  74. data/test/configuration/loading_test.rb +119 -0
  75. data/test/configuration/namespace_dsl_test.rb +283 -0
  76. data/test/configuration/roles_test.rb +47 -0
  77. data/test/configuration/servers_test.rb +90 -0
  78. data/test/configuration/variables_test.rb +180 -0
  79. data/test/configuration_test.rb +60 -212
  80. data/test/deploy/scm/base_test.rb +55 -0
  81. data/test/deploy/strategy/copy_test.rb +146 -0
  82. data/test/extensions_test.rb +69 -0
  83. data/test/fixtures/cli_integration.rb +5 -0
  84. data/test/fixtures/custom.rb +2 -2
  85. data/test/gateway_test.rb +167 -0
  86. data/test/logger_test.rb +123 -0
  87. data/test/server_definition_test.rb +108 -0
  88. data/test/shell_test.rb +64 -0
  89. data/test/ssh_test.rb +67 -154
  90. data/test/task_definition_test.rb +101 -0
  91. data/test/upload_test.rb +131 -0
  92. data/test/utils.rb +31 -39
  93. data/test/version_test.rb +24 -0
  94. metadata +145 -98
  95. data/THANKS +0 -4
  96. data/lib/capistrano/actor.rb +0 -567
  97. data/lib/capistrano/generators/rails/deployment/deployment_generator.rb +0 -25
  98. data/lib/capistrano/generators/rails/deployment/templates/capistrano.rake +0 -49
  99. data/lib/capistrano/generators/rails/deployment/templates/deploy.rb +0 -122
  100. data/lib/capistrano/generators/rails/loader.rb +0 -20
  101. data/lib/capistrano/scm/base.rb +0 -61
  102. data/lib/capistrano/scm/baz.rb +0 -118
  103. data/lib/capistrano/scm/bzr.rb +0 -70
  104. data/lib/capistrano/scm/cvs.rb +0 -129
  105. data/lib/capistrano/scm/darcs.rb +0 -27
  106. data/lib/capistrano/scm/mercurial.rb +0 -83
  107. data/lib/capistrano/scm/perforce.rb +0 -139
  108. data/lib/capistrano/scm/subversion.rb +0 -128
  109. data/lib/capistrano/transfer.rb +0 -97
  110. data/lib/capistrano/utils.rb +0 -26
  111. data/test/actor_test.rb +0 -402
  112. data/test/scm/cvs_test.rb +0 -196
  113. data/test/scm/subversion_test.rb +0 -145
@@ -1,97 +0,0 @@
1
- begin
2
- require 'capistrano/version'
3
-
4
- begin
5
- require 'rubygems'
6
- gem 'net-sftp', '< 1.99.0'
7
- rescue LoadError, NameError
8
- end
9
-
10
- require 'net/sftp'
11
- require 'net/sftp/version'
12
-
13
- sftp_version = [Net::SFTP::Version::MAJOR, Net::SFTP::Version::MINOR, Net::SFTP::Version::TINY]
14
- if !Capistrano::Version.check(sftp_version, Capistrano::Version::MINIMUM_SFTP_REQUIRED, Capistrano::Version::MAXIMUM_SFTP_REQUIRED)
15
- warn "You have Net::SFTP #{sftp_version.join(".")}, but you need between #{Capistrano::Version::MINIMUM_SFTP_REQUIRED.join('.')}...#{Capistrano::Version::MAXIMUM_SFTP_REQUIRED.join('.')}. Net::SFTP will not be used."
16
- Capistrano::SFTP = false
17
- else
18
- Capistrano::SFTP = true
19
- end
20
- rescue LoadError
21
- Capistrano::SFTP = false
22
- end
23
-
24
- module Capistrano
25
-
26
- # This class encapsulates a single file transfer to be performed in parallel
27
- # across multiple machines, using the SFTP protocol.
28
- class Transfer
29
- def initialize(servers, actor, filename, params={}) #:nodoc:
30
- @servers = servers
31
- @actor = actor
32
- @filename = filename
33
- @params = params
34
- @completed = 0
35
- @failed = 0
36
- @sftps = setup_transfer
37
- end
38
-
39
- def logger #:nodoc:
40
- @actor.logger
41
- end
42
-
43
- # Uploads to all specified servers in parallel.
44
- def process!
45
- logger.debug "uploading #{@filename}"
46
-
47
- loop do
48
- @sftps.each { |sftp| sftp.channel.connection.process(true) }
49
- break if @completed == @servers.length
50
- end
51
-
52
- logger.trace "upload finished"
53
-
54
- if @failed > 0
55
- raise "upload of #{@filename} failed on one or more hosts"
56
- end
57
-
58
- self
59
- end
60
-
61
- private
62
-
63
- def setup_transfer
64
- @servers.map do |server|
65
- sftp = @actor.sessions[server].sftp
66
- sftp.connect unless sftp.state == :open
67
-
68
- sftp.open(@filename, IO::WRONLY | IO::CREAT | IO::TRUNC, @params[:mode] || 0660) do |status, handle|
69
- break unless check_status("open #{@filename}", server, status)
70
-
71
- logger.info "uploading data to #{server}:#{@filename}"
72
- sftp.write(handle, @params[:data] || "") do |status|
73
- break unless check_status("write to #{server}:#{@filename}", server, status)
74
- sftp.close_handle(handle) do
75
- logger.debug "done uploading data to #{server}:#{@filename}"
76
- @completed += 1
77
- end
78
- end
79
- end
80
-
81
- sftp
82
- end
83
- end
84
-
85
- def check_status(action, server, status)
86
- if status.code != Net::SFTP::Session::FX_OK
87
- logger.error "could not #{action} on #{server} (#{status.message})"
88
- @failed += 1
89
- @completed += 1
90
- return false
91
- end
92
-
93
- true
94
- end
95
- end
96
-
97
- end
@@ -1,26 +0,0 @@
1
- module Capistrano
2
- # A helper method for converting a comma-delimited string into an array of
3
- # roles.
4
- def self.str2roles(string)
5
- list = string.split(/,/).map { |s| s.strip.to_sym }
6
- list.empty? ? nil : list
7
- end
8
-
9
- # Used by third-party task bundles to identify the capistrano configuration
10
- # that is loading them. It's return value is not reliable in other contexts.
11
- # If +require_config+ is not false, an exception will be raised if the current
12
- # configuration is not set.
13
- def self.configuration(require_config=false)
14
- config = Thread.current[:capistrano_configuration]
15
- if require_config && config.nil?
16
- raise "Please require this file from within a Capistrano recipe"
17
- end
18
- config
19
- end
20
-
21
- # Used internally by Capistrano to specify the current configuration before
22
- # loading a third-party task bundle.
23
- def self.configuration=(config)
24
- Thread.current[:capistrano_configuration] = config
25
- end
26
- end
@@ -1,402 +0,0 @@
1
- $:.unshift File.dirname(__FILE__) + "/../lib"
2
-
3
- require 'stringio'
4
- require 'test/unit'
5
- require 'capistrano/actor'
6
- require 'capistrano/logger'
7
- require 'capistrano/configuration'
8
-
9
- class ActorTest < Test::Unit::TestCase
10
-
11
- class TestingConnectionFactory
12
- def initialize(config)
13
- end
14
-
15
- def connect_to(server)
16
- server
17
- end
18
- end
19
-
20
- class GatewayConnectionFactory
21
- def connect_to(server)
22
- server
23
- end
24
- end
25
-
26
- class TestingCommand
27
- def self.invoked!
28
- @invoked = true
29
- end
30
-
31
- def self.invoked?
32
- @invoked
33
- end
34
-
35
- def self.reset!
36
- @invoked = nil
37
- end
38
-
39
- def initialize(*args)
40
- end
41
-
42
- def process!
43
- self.class.invoked!
44
- end
45
- end
46
-
47
- class TestActor < Capistrano::Actor
48
- attr_reader :factory
49
-
50
- self.connection_factory = TestingConnectionFactory
51
- self.command_factory = TestingCommand
52
-
53
- def establish_gateway
54
- GatewayConnectionFactory.new
55
- end
56
- end
57
-
58
- class MockConfiguration < Capistrano::Configuration
59
- Role = Struct.new(:host, :options)
60
-
61
- attr_accessor :gateway, :pretend
62
-
63
- def initialize(*args)
64
- super
65
- @logger = Capistrano::Logger.new(:output => StringIO.new)
66
- end
67
-
68
- def delegated_method
69
- "result of method"
70
- end
71
-
72
- ROLES = { :db => [ Role.new("01.example.com", :primary => true),
73
- Role.new("02.example.com", {}),
74
- Role.new("all.example.com", {})],
75
- :web => [ Role.new("03.example.com", {}),
76
- Role.new("04.example.com", {}),
77
- Role.new("all.example.com", {})],
78
- :app => [ Role.new("05.example.com", {}),
79
- Role.new("06.example.com", {}),
80
- Role.new("07.example.com", {}),
81
- Role.new("all.example.com", {})] }
82
-
83
- def roles
84
- ROLES
85
- end
86
- end
87
-
88
- module CustomExtension
89
- def do_something_extra(a, b, c)
90
- run "echo '#{a} :: #{b} :: #{c}'"
91
- end
92
- end
93
-
94
- def setup
95
- TestingCommand.reset!
96
- @actor = TestActor.new(MockConfiguration.new)
97
- ENV["ROLES"] = nil
98
- ENV["HOSTS"] = nil
99
- end
100
-
101
- def test_previous_release_returns_nil_with_one_release
102
- class << @actor
103
- def releases
104
- ["1234567890"]
105
- end
106
- end
107
- assert_equal @actor.previous_release, nil
108
- end
109
-
110
- def test_define_task_creates_method
111
- @actor.define_task :hello do
112
- "result"
113
- end
114
- assert @actor.respond_to?(:hello)
115
- assert_equal "result", @actor.hello
116
- end
117
-
118
- def test_define_task_with_successful_transaction
119
- class << @actor
120
- attr_reader :rolled_back
121
- attr_reader :history
122
- end
123
-
124
- @actor.define_task :hello do
125
- (@history ||= []) << :hello
126
- on_rollback { @rolled_back = true }
127
- "hello"
128
- end
129
-
130
- @actor.define_task :goodbye do
131
- (@history ||= []) << :goodbye
132
- transaction do
133
- hello
134
- end
135
- "goodbye"
136
- end
137
-
138
- assert_nothing_raised { @actor.goodbye }
139
- assert !@actor.rolled_back
140
- assert_equal [:goodbye, :hello], @actor.history
141
- end
142
-
143
- def test_define_task_with_failed_transaction
144
- class << @actor
145
- attr_reader :rolled_back
146
- attr_reader :history
147
- end
148
-
149
- @actor.define_task :hello do
150
- (@history ||= []) << :hello
151
- on_rollback { @rolled_back = true }
152
- "hello"
153
- end
154
-
155
- @actor.define_task :goodbye do
156
- (@history ||= []) << :goodbye
157
- transaction do
158
- hello
159
- raise "ouch"
160
- end
161
- "goodbye"
162
- end
163
-
164
- assert_raise(RuntimeError) do
165
- @actor.goodbye
166
- end
167
-
168
- assert @actor.rolled_back
169
- assert_equal [:goodbye, :hello], @actor.history
170
- end
171
-
172
- def test_rollback_uses_roles_for_associated_task
173
- @actor.define_task :inner, :roles => :db do
174
- on_rollback { run "error" }
175
- run "go"
176
- raise "fail"
177
- end
178
-
179
- @actor.define_task :outer do
180
- transaction do
181
- inner
182
- end
183
- run "done"
184
- end
185
-
186
- assert_raise(RuntimeError) { @actor.outer }
187
-
188
- assert TestingCommand.invoked?
189
- assert_equal %w(01.example.com 02.example.com all.example.com), @actor.sessions.keys.sort
190
- end
191
-
192
- def test_delegates_to_configuration
193
- @actor.define_task :hello do
194
- delegated_method
195
- end
196
- assert_equal "result of method", @actor.hello
197
- end
198
-
199
- def test_task_servers_with_duplicates
200
- @actor.define_task :foo do
201
- run "do this"
202
- end
203
-
204
- assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.tasks[:foo].servers.sort
205
- end
206
-
207
- def test_run_in_task_without_explicit_roles_selects_all_roles
208
- @actor.define_task :foo do
209
- run "do this"
210
- end
211
-
212
- @actor.foo
213
- assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.sessions.keys.sort
214
- end
215
-
216
- def test_run_in_task_with_single_role_selects_that_role
217
- @actor.define_task :foo, :roles => :db do
218
- run "do this"
219
- end
220
-
221
- @actor.foo
222
- assert_equal %w(01.example.com 02.example.com all.example.com), @actor.sessions.keys.sort
223
- end
224
-
225
- def test_run_in_task_with_single_role_selects_that_role_from_environment
226
- ENV["ROLES"] = "app"
227
- @actor.define_task :foo, :roles => :db do
228
- run "do this"
229
- end
230
-
231
- @actor.foo
232
- assert_equal %w(05.example.com 06.example.com 07.example.com all.example.com), @actor.sessions.keys.sort
233
- end
234
-
235
- def test_run_in_task_with_multiple_roles_selects_those_roles
236
- @actor.define_task :foo, :roles => [:db, :web] do
237
- run "do this"
238
- end
239
-
240
- @actor.foo
241
- assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com all.example.com), @actor.sessions.keys.sort
242
- end
243
-
244
- def test_run_in_task_with_multiple_roles_selects_those_roles_from_environment
245
- ENV["ROLES"] = "app,db"
246
- @actor.define_task :foo, :roles => [:db, :web] do
247
- run "do this"
248
- end
249
-
250
- @actor.foo
251
- assert_equal %w(01.example.com 02.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.sessions.keys.sort
252
- end
253
-
254
- def test_run_in_task_with_only_restricts_selected_roles
255
- @actor.define_task :foo, :roles => :db, :only => { :primary => true } do
256
- run "do this"
257
- end
258
-
259
- @actor.foo
260
- assert_equal %w(01.example.com), @actor.sessions.keys.sort
261
- end
262
-
263
- def test_run_in_task_with_except_restricts_selected_roles
264
- @actor.define_task :foo, :roles => :db, :except => { :primary => true } do
265
- run "do this"
266
- end
267
-
268
- @actor.foo
269
- assert_equal %w(02.example.com all.example.com), @actor.sessions.keys.sort
270
- end
271
-
272
- def test_run_in_task_with_single_host_selected
273
- @actor.define_task :foo, :hosts => "01.example.com" do
274
- run "do this"
275
- end
276
-
277
- @actor.foo
278
- assert_equal %w(01.example.com), @actor.sessions.keys.sort
279
- end
280
-
281
- def test_run_in_task_with_single_host_selected_from_environment
282
- ENV["HOSTS"] = "02.example.com"
283
- @actor.define_task :foo, :hosts => "01.example.com" do
284
- run "do this"
285
- end
286
-
287
- @actor.foo
288
- assert_equal %w(02.example.com), @actor.sessions.keys.sort
289
- end
290
-
291
- def test_run_in_task_with_multiple_hosts_selected
292
- @actor.define_task :foo, :hosts => [ "01.example.com", "07.example.com" ] do
293
- run "do this"
294
- end
295
-
296
- @actor.foo
297
- assert_equal %w(01.example.com 07.example.com), @actor.sessions.keys.sort
298
- end
299
-
300
- def test_run_in_task_with_multiple_hosts_selected_from_environment
301
- ENV["HOSTS"] = "02.example.com,06.example.com"
302
- @actor.define_task :foo, :hosts => [ "01.example.com", "07.example.com" ] do
303
- run "do this"
304
- end
305
-
306
- @actor.foo
307
- assert_equal %w(02.example.com 06.example.com), @actor.sessions.keys.sort
308
- end
309
-
310
- def test_establish_connection_uses_gateway_if_specified
311
- @actor.configuration.gateway = "10.example.com"
312
- @actor.define_task :foo, :roles => :db do
313
- run "do this"
314
- end
315
-
316
- @actor.foo
317
- assert_instance_of GatewayConnectionFactory, @actor.factory
318
- end
319
-
320
- def test_establish_connection_uses_gateway_if_specified_with_username_and_port
321
- @actor.configuration.gateway = "demo@10.example.com:8088"
322
- @actor.define_task :foo, :roles => :db do
323
- run "do this"
324
- end
325
- @actor.foo
326
- assert_instance_of GatewayConnectionFactory, @actor.factory
327
- end
328
-
329
- def test_run_when_not_pretend
330
- @actor.define_task :foo do
331
- run "do this"
332
- end
333
-
334
- @actor.configuration.pretend = false
335
- @actor.foo
336
- assert TestingCommand.invoked?
337
- end
338
-
339
- def test_run_when_pretend
340
- @actor.define_task :foo do
341
- run "do this"
342
- end
343
-
344
- @actor.configuration.pretend = true
345
- @actor.foo
346
- assert !TestingCommand.invoked?
347
- end
348
-
349
- def test_task_before_hook
350
- history = []
351
- @actor.define_task :foo do
352
- history << "foo"
353
- end
354
-
355
- @actor.define_task :before_foo do
356
- history << "before_foo"
357
- end
358
-
359
- @actor.foo
360
- assert_equal %w(before_foo foo), history
361
- end
362
-
363
- def test_task_after_hook
364
- history = []
365
- @actor.define_task :foo do
366
- history << "foo"
367
- end
368
-
369
- @actor.define_task :after_foo do
370
- history << "after_foo"
371
- end
372
-
373
- @actor.foo
374
- assert_equal %w(foo after_foo), history
375
- end
376
-
377
- def test_uppercase_variables
378
- config = Capistrano::Configuration.new(TestActor)
379
- config.set :HELLO, "world"
380
- assert_equal "world", config.actor.instance_eval("HELLO")
381
- config.set :HELLO, "test"
382
- assert_equal "test", config.actor.instance_eval("HELLO")
383
- end
384
-
385
- def test_connect_when_no_matching_servers
386
- @actor.define_task :foo, :roles => :db, :only => { :fnoofy => true } do
387
- run "do this"
388
- end
389
-
390
- assert_raises(RuntimeError) { @actor.foo }
391
- end
392
-
393
- def test_custom_extension
394
- assert Capistrano.plugin(:custom, CustomExtension)
395
- @actor.define_task :foo, :roles => :db do
396
- custom.do_something_extra(1, 2, 3)
397
- end
398
- assert_nothing_raised { @actor.foo }
399
- assert TestingCommand.invoked?
400
- assert Capistrano.remove_plugin(:custom)
401
- end
402
- end