capistrano 1.1.0

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