capistrano 1.1.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 (37) hide show
  1. data/bin/cap +11 -0
  2. data/examples/sample.rb +113 -0
  3. data/lib/capistrano.rb +1 -0
  4. data/lib/capistrano/actor.rb +438 -0
  5. data/lib/capistrano/cli.rb +295 -0
  6. data/lib/capistrano/command.rb +90 -0
  7. data/lib/capistrano/configuration.rb +243 -0
  8. data/lib/capistrano/extensions.rb +38 -0
  9. data/lib/capistrano/gateway.rb +118 -0
  10. data/lib/capistrano/generators/rails/deployment/deployment_generator.rb +25 -0
  11. data/lib/capistrano/generators/rails/deployment/templates/capistrano.rake +46 -0
  12. data/lib/capistrano/generators/rails/deployment/templates/deploy.rb +122 -0
  13. data/lib/capistrano/generators/rails/loader.rb +20 -0
  14. data/lib/capistrano/logger.rb +59 -0
  15. data/lib/capistrano/recipes/standard.rb +242 -0
  16. data/lib/capistrano/recipes/templates/maintenance.rhtml +53 -0
  17. data/lib/capistrano/scm/base.rb +62 -0
  18. data/lib/capistrano/scm/baz.rb +118 -0
  19. data/lib/capistrano/scm/bzr.rb +70 -0
  20. data/lib/capistrano/scm/cvs.rb +124 -0
  21. data/lib/capistrano/scm/darcs.rb +27 -0
  22. data/lib/capistrano/scm/perforce.rb +139 -0
  23. data/lib/capistrano/scm/subversion.rb +122 -0
  24. data/lib/capistrano/ssh.rb +39 -0
  25. data/lib/capistrano/transfer.rb +90 -0
  26. data/lib/capistrano/utils.rb +26 -0
  27. data/lib/capistrano/version.rb +30 -0
  28. data/test/actor_test.rb +294 -0
  29. data/test/command_test.rb +43 -0
  30. data/test/configuration_test.rb +233 -0
  31. data/test/fixtures/config.rb +5 -0
  32. data/test/fixtures/custom.rb +3 -0
  33. data/test/scm/cvs_test.rb +186 -0
  34. data/test/scm/subversion_test.rb +137 -0
  35. data/test/ssh_test.rb +104 -0
  36. data/test/utils.rb +50 -0
  37. metadata +107 -0
@@ -0,0 +1,294 @@
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
59
+ Role = Struct.new(:host, :options)
60
+
61
+ attr_accessor :gateway, :pretend
62
+
63
+ def delegated_method
64
+ "result of method"
65
+ end
66
+
67
+ ROLES = { :db => [ Role.new("01.example.com", :primary => true),
68
+ Role.new("02.example.com", {}),
69
+ Role.new("all.example.com", {})],
70
+ :web => [ Role.new("03.example.com", {}),
71
+ Role.new("04.example.com", {}),
72
+ Role.new("all.example.com", {})],
73
+ :app => [ Role.new("05.example.com", {}),
74
+ Role.new("06.example.com", {}),
75
+ Role.new("07.example.com", {}),
76
+ Role.new("all.example.com", {})] }
77
+
78
+ def roles
79
+ ROLES
80
+ end
81
+
82
+ def logger
83
+ @logger ||= Capistrano::Logger.new(:output => StringIO.new)
84
+ end
85
+ end
86
+
87
+ module CustomExtension
88
+ def do_something_extra(a, b, c)
89
+ run "echo '#{a} :: #{b} :: #{c}'"
90
+ end
91
+ end
92
+
93
+ def setup
94
+ TestingCommand.reset!
95
+ @actor = TestActor.new(MockConfiguration.new)
96
+ end
97
+
98
+ def test_define_task_creates_method
99
+ @actor.define_task :hello do
100
+ "result"
101
+ end
102
+ assert @actor.respond_to?(:hello)
103
+ assert_equal "result", @actor.hello
104
+ end
105
+
106
+ def test_define_task_with_successful_transaction
107
+ class << @actor
108
+ attr_reader :rolled_back
109
+ attr_reader :history
110
+ end
111
+
112
+ @actor.define_task :hello do
113
+ (@history ||= []) << :hello
114
+ on_rollback { @rolled_back = true }
115
+ "hello"
116
+ end
117
+
118
+ @actor.define_task :goodbye do
119
+ (@history ||= []) << :goodbye
120
+ transaction do
121
+ hello
122
+ end
123
+ "goodbye"
124
+ end
125
+
126
+ assert_nothing_raised { @actor.goodbye }
127
+ assert !@actor.rolled_back
128
+ assert_equal [:goodbye, :hello], @actor.history
129
+ end
130
+
131
+ def test_define_task_with_failed_transaction
132
+ class << @actor
133
+ attr_reader :rolled_back
134
+ attr_reader :history
135
+ end
136
+
137
+ @actor.define_task :hello do
138
+ (@history ||= []) << :hello
139
+ on_rollback { @rolled_back = true }
140
+ "hello"
141
+ end
142
+
143
+ @actor.define_task :goodbye do
144
+ (@history ||= []) << :goodbye
145
+ transaction do
146
+ hello
147
+ raise "ouch"
148
+ end
149
+ "goodbye"
150
+ end
151
+
152
+ assert_raise(RuntimeError) do
153
+ @actor.goodbye
154
+ end
155
+
156
+ assert @actor.rolled_back
157
+ assert_equal [:goodbye, :hello], @actor.history
158
+ end
159
+
160
+ def test_delegates_to_configuration
161
+ @actor.define_task :hello do
162
+ delegated_method
163
+ end
164
+ assert_equal "result of method", @actor.hello
165
+ end
166
+
167
+ def test_task_servers_with_duplicates
168
+ @actor.define_task :foo do
169
+ run "do this"
170
+ end
171
+
172
+ 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
173
+ end
174
+
175
+ def test_run_in_task_without_explicit_roles_selects_all_roles
176
+ @actor.define_task :foo do
177
+ run "do this"
178
+ end
179
+
180
+ @actor.foo
181
+ 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
182
+ end
183
+
184
+ def test_run_in_task_with_single_role_selects_that_role
185
+ @actor.define_task :foo, :roles => :db do
186
+ run "do this"
187
+ end
188
+
189
+ @actor.foo
190
+ assert_equal %w(01.example.com 02.example.com all.example.com), @actor.sessions.keys.sort
191
+ end
192
+
193
+ def test_run_in_task_with_multiple_roles_selects_those_roles
194
+ @actor.define_task :foo, :roles => [:db, :web] do
195
+ run "do this"
196
+ end
197
+
198
+ @actor.foo
199
+ assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com all.example.com), @actor.sessions.keys.sort
200
+ end
201
+
202
+ def test_run_in_task_with_only_restricts_selected_roles
203
+ @actor.define_task :foo, :roles => :db, :only => { :primary => true } do
204
+ run "do this"
205
+ end
206
+
207
+ @actor.foo
208
+ assert_equal %w(01.example.com), @actor.sessions.keys.sort
209
+ end
210
+
211
+ def test_establish_connection_uses_gateway_if_specified
212
+ @actor.configuration.gateway = "10.example.com"
213
+ @actor.define_task :foo, :roles => :db do
214
+ run "do this"
215
+ end
216
+
217
+ @actor.foo
218
+ assert_instance_of GatewayConnectionFactory, @actor.factory
219
+ end
220
+
221
+ def test_run_when_not_pretend
222
+ @actor.define_task :foo do
223
+ run "do this"
224
+ end
225
+
226
+ @actor.configuration.pretend = false
227
+ @actor.foo
228
+ assert TestingCommand.invoked?
229
+ end
230
+
231
+ def test_run_when_pretend
232
+ @actor.define_task :foo do
233
+ run "do this"
234
+ end
235
+
236
+ @actor.configuration.pretend = true
237
+ @actor.foo
238
+ assert !TestingCommand.invoked?
239
+ end
240
+
241
+ def test_task_before_hook
242
+ history = []
243
+ @actor.define_task :foo do
244
+ history << "foo"
245
+ end
246
+
247
+ @actor.define_task :before_foo do
248
+ history << "before_foo"
249
+ end
250
+
251
+ @actor.foo
252
+ assert_equal %w(before_foo foo), history
253
+ end
254
+
255
+ def test_task_after_hook
256
+ history = []
257
+ @actor.define_task :foo do
258
+ history << "foo"
259
+ end
260
+
261
+ @actor.define_task :after_foo do
262
+ history << "after_foo"
263
+ end
264
+
265
+ @actor.foo
266
+ assert_equal %w(foo after_foo), history
267
+ end
268
+
269
+ def test_uppercase_variables
270
+ config = Capistrano::Configuration.new(TestActor)
271
+ config.set :HELLO, "world"
272
+ assert_equal "world", config.actor.instance_eval("HELLO")
273
+ config.set :HELLO, "test"
274
+ assert_equal "test", config.actor.instance_eval("HELLO")
275
+ end
276
+
277
+ def test_connect_when_no_matching_servers
278
+ @actor.define_task :foo, :roles => :db, :only => { :fnoofy => true } do
279
+ run "do this"
280
+ end
281
+
282
+ assert_raises(RuntimeError) { @actor.foo }
283
+ end
284
+
285
+ def test_custom_extension
286
+ assert Capistrano.plugin(:custom, CustomExtension)
287
+ @actor.define_task :foo, :roles => :db do
288
+ custom.do_something_extra(1, 2, 3)
289
+ end
290
+ assert_nothing_raised { @actor.foo }
291
+ assert TestingCommand.invoked?
292
+ assert Capistrano.remove_plugin(:custom)
293
+ end
294
+ end
@@ -0,0 +1,43 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'stringio'
4
+ require 'test/unit'
5
+ require 'capistrano/command'
6
+
7
+ class CommandTest < Test::Unit::TestCase
8
+ class MockSession
9
+ def open_channel
10
+ { :closed => true, :status => 0 }
11
+ end
12
+ end
13
+
14
+ class MockActor
15
+ attr_reader :sessions
16
+
17
+ def initialize
18
+ @sessions = Hash.new { |h,k| h[k] = MockSession.new }
19
+ end
20
+ end
21
+
22
+ def setup
23
+ @actor = MockActor.new
24
+ end
25
+
26
+ def test_command_executes_on_all_servers
27
+ command = Capistrano::Command.new(%w(server1 server2 server3),
28
+ "hello", nil, {}, @actor)
29
+ assert_equal %w(server1 server2 server3), @actor.sessions.keys.sort
30
+ end
31
+
32
+ def test_command_with_newlines
33
+ command = Capistrano::Command.new(%w(server1), "hello\nworld", nil, {},
34
+ @actor)
35
+ assert_equal "hello\\\nworld", command.command
36
+ end
37
+
38
+ def test_command_with_windows_newlines
39
+ command = Capistrano::Command.new(%w(server1), "hello\r\nworld", nil, {},
40
+ @actor)
41
+ assert_equal "hello\\\nworld", command.command
42
+ end
43
+ end
@@ -0,0 +1,233 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'test/unit'
4
+ require 'capistrano/configuration'
5
+ require 'flexmock'
6
+
7
+ class ConfigurationTest < Test::Unit::TestCase
8
+ class MockActor
9
+ attr_reader :tasks
10
+
11
+ def initialize(config)
12
+ end
13
+
14
+ def define_task(*args, &block)
15
+ (@tasks ||= []).push [args, block].flatten
16
+ end
17
+ end
18
+
19
+ class MockSCM
20
+ attr_reader :configuration
21
+
22
+ def initialize(config)
23
+ @configuration = config
24
+ end
25
+ end
26
+
27
+ def setup
28
+ @config = Capistrano::Configuration.new(MockActor)
29
+ @config.set :scm, MockSCM
30
+ end
31
+
32
+ def test_version_dir_default
33
+ assert "releases", @config.version_dir
34
+ end
35
+
36
+ def test_current_dir_default
37
+ assert "current", @config.current_dir
38
+ end
39
+
40
+ def test_shared_dir_default
41
+ assert "shared", @config.shared_dir
42
+ end
43
+
44
+ def test_set_repository
45
+ @config.set :repository, "/foo/bar/baz"
46
+ assert_equal "/foo/bar/baz", @config.repository
47
+ end
48
+
49
+ def test_set_user
50
+ @config.set :user, "flippy"
51
+ assert_equal "flippy", @config.user
52
+ end
53
+
54
+ def test_define_single_role
55
+ @config.role :app, "somewhere.example.com"
56
+ assert_equal 1, @config.roles[:app].length
57
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
58
+ assert_equal Hash.new, @config.roles[:app].first.options
59
+ end
60
+
61
+ def test_define_single_role_with_options
62
+ @config.role :app, "somewhere.example.com", :primary => true
63
+ assert_equal 1, @config.roles[:app].length
64
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
65
+ assert_equal({:primary => true}, @config.roles[:app].first.options)
66
+ end
67
+
68
+ def test_define_multi_role
69
+ @config.role :app, "somewhere.example.com", "else.example.com"
70
+ assert_equal 2, @config.roles[:app].length
71
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
72
+ assert_equal "else.example.com", @config.roles[:app].last.host
73
+ assert_equal({}, @config.roles[:app].first.options)
74
+ assert_equal({}, @config.roles[:app].last.options)
75
+ end
76
+
77
+ def test_define_multi_role_with_options
78
+ @config.role :app, "somewhere.example.com", "else.example.com", :primary => true
79
+ assert_equal 2, @config.roles[:app].length
80
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
81
+ assert_equal "else.example.com", @config.roles[:app].last.host
82
+ assert_equal({:primary => true}, @config.roles[:app].first.options)
83
+ assert_equal({:primary => true}, @config.roles[:app].last.options)
84
+ end
85
+
86
+ def test_load_string_unnamed
87
+ @config.load :string => "set :repository, __FILE__"
88
+ assert_equal "<eval>", @config.repository
89
+ end
90
+
91
+ def test_load_string_named
92
+ @config.load :string => "set :repository, __FILE__", :name => "test.rb"
93
+ assert_equal "test.rb", @config.repository
94
+ end
95
+
96
+ def test_load
97
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
98
+ @config.load file
99
+ assert_equal "1/2/foo", @config.repository
100
+ assert_equal "./#{file}.example.com", @config.gateway
101
+ assert_equal 1, @config.roles[:web].length
102
+ end
103
+
104
+ def test_load_explicit_name
105
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
106
+ @config.load file, :name => "config"
107
+ assert_equal "1/2/foo", @config.repository
108
+ assert_equal "config.example.com", @config.gateway
109
+ assert_equal 1, @config.roles[:web].length
110
+ end
111
+
112
+ def test_load_file_implied_name
113
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
114
+ @config.load :file => file
115
+ assert_equal "1/2/foo", @config.repository
116
+ assert_equal "./#{file}.example.com", @config.gateway
117
+ assert_equal 1, @config.roles[:web].length
118
+ end
119
+
120
+ def test_load_file_explicit_name
121
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
122
+ @config.load :file => file, :name => "config"
123
+ assert_equal "1/2/foo", @config.repository
124
+ assert_equal "config.example.com", @config.gateway
125
+ assert_equal 1, @config.roles[:web].length
126
+ end
127
+
128
+ def test_load_proc_explicit
129
+ @config.load :proc => Proc.new { set :gateway, "nifty.zoo.test" }
130
+ assert_equal "nifty.zoo.test", @config.gateway
131
+ end
132
+
133
+ def test_load_proc_implicit
134
+ @config.load { set :gateway, "nifty.zoo.test" }
135
+ assert_equal "nifty.zoo.test", @config.gateway
136
+ end
137
+
138
+ def test_task_without_options
139
+ block = Proc.new { }
140
+ @config.task :hello, &block
141
+ assert_equal 1, @config.actor.tasks.length
142
+ assert_equal :hello, @config.actor.tasks[0][0]
143
+ assert_equal({}, @config.actor.tasks[0][1])
144
+ assert_equal block, @config.actor.tasks[0][2]
145
+ end
146
+
147
+ def test_task_with_options
148
+ block = Proc.new { }
149
+ @config.task :hello, :roles => :app, &block
150
+ assert_equal 1, @config.actor.tasks.length
151
+ assert_equal :hello, @config.actor.tasks[0][0]
152
+ assert_equal({:roles => :app}, @config.actor.tasks[0][1])
153
+ assert_equal block, @config.actor.tasks[0][2]
154
+ end
155
+
156
+ def test_source
157
+ @config.set :repository, "/foo/bar/baz"
158
+ assert_equal "/foo/bar/baz", @config.source.configuration.repository
159
+ end
160
+
161
+ def test_releases_path_default
162
+ @config.set :deploy_to, "/start/of/path"
163
+ assert_equal "/start/of/path/releases", @config.releases_path
164
+ end
165
+
166
+ def test_releases_path_custom
167
+ @config.set :deploy_to, "/start/of/path"
168
+ @config.set :version_dir, "right/here"
169
+ assert_equal "/start/of/path/right/here", @config.releases_path
170
+ end
171
+
172
+ def test_current_path_default
173
+ @config.set :deploy_to, "/start/of/path"
174
+ assert_equal "/start/of/path/current", @config.current_path
175
+ end
176
+
177
+ def test_current_path_custom
178
+ @config.set :deploy_to, "/start/of/path"
179
+ @config.set :current_dir, "right/here"
180
+ assert_equal "/start/of/path/right/here", @config.current_path
181
+ end
182
+
183
+ def test_shared_path_default
184
+ @config.set :deploy_to, "/start/of/path"
185
+ assert_equal "/start/of/path/shared", @config.shared_path
186
+ end
187
+
188
+ def test_shared_path_custom
189
+ @config.set :deploy_to, "/start/of/path"
190
+ @config.set :shared_dir, "right/here"
191
+ assert_equal "/start/of/path/right/here", @config.shared_path
192
+ end
193
+
194
+ def test_release_path_implicit
195
+ @config.set :deploy_to, "/start/of/path"
196
+ assert_equal "/start/of/path/releases/#{@config.now.strftime("%Y%m%d%H%M%S")}", @config.release_path
197
+ end
198
+
199
+ def test_release_path_explicit
200
+ @config.set :deploy_to, "/start/of/path"
201
+ assert_equal "/start/of/path/releases/silly", @config.release_path("silly")
202
+ end
203
+
204
+ def test_task_description
205
+ block = Proc.new { }
206
+ @config.desc "A sample task"
207
+ @config.task :hello, &block
208
+ assert_equal "A sample task", @config.actor.tasks[0][1][:desc]
209
+ end
210
+
211
+ def test_set_scm_to_darcs
212
+ @config.set :scm, :darcs
213
+ assert_equal "Capistrano::SCM::Darcs", @config.source.class.name
214
+ end
215
+
216
+ def test_set_scm_to_subversion
217
+ @config.set :scm, :subversion
218
+ assert_equal "Capistrano::SCM::Subversion", @config.source.class.name
219
+ end
220
+
221
+ def test_get_proc_variable_sets_original_value_hash
222
+ @config.set(:proc) { "foo" }
223
+ assert_nil @config[:original_value][:proc]
224
+ assert_equal "foo", @config[:proc]
225
+ assert_not_nil @config[:original_value][:proc]
226
+ assert @config[:original_value][:proc].respond_to?(:call)
227
+ end
228
+
229
+ def test_require
230
+ @config.require "#{File.dirname(__FILE__)}/fixtures/custom"
231
+ assert_equal "foo", @config.gateway
232
+ end
233
+ end