capistrano 3.0.0.pre2 → 3.0.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/README.md +108 -4
- data/lib/capistrano/application.rb +16 -1
- data/lib/capistrano/configuration.rb +12 -17
- data/lib/capistrano/configuration/server.rb +68 -3
- data/lib/capistrano/configuration/servers.rb +71 -28
- data/lib/capistrano/dsl.rb +2 -0
- data/lib/capistrano/dsl/env.rb +7 -4
- data/lib/capistrano/i18n.rb +2 -1
- data/lib/capistrano/tasks/deploy.rake +3 -6
- data/lib/capistrano/templates/Capfile +4 -0
- data/lib/capistrano/version.rb +1 -1
- data/spec/integration/deploy_finalize_spec.rb +34 -0
- data/spec/integration/deploy_finished_spec.rb +36 -0
- data/spec/integration/deploy_started_spec.rb +74 -0
- data/spec/integration/deploy_update_spec.rb +45 -0
- data/spec/integration/dsl_spec.rb +254 -0
- data/spec/integration/installation_spec.rb +76 -0
- data/spec/integration_spec_helper.rb +7 -0
- data/spec/lib/capistrano/application_spec.rb +61 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +91 -0
- data/spec/lib/capistrano/configuration/servers_spec.rb +79 -11
- data/spec/lib/capistrano/configuration_spec.rb +12 -2
- data/spec/lib/capistrano/dsl/env_spec.rb +0 -73
- data/spec/spec_helper.rb +2 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/support/test_app.rb +89 -0
- metadata +24 -2
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'integration_spec_helper'
|
2
|
+
|
3
|
+
describe 'cap install', slow: true do
|
4
|
+
|
5
|
+
context 'with defaults' do
|
6
|
+
before :all do
|
7
|
+
create_test_app
|
8
|
+
Dir.chdir(test_app_path) do
|
9
|
+
%x[bundle exec cap install]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'installation' do
|
14
|
+
|
15
|
+
it 'creates config/deploy' do
|
16
|
+
path = test_app_path.join('config/deploy')
|
17
|
+
expect(Dir.exists?(path)).to be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'creates lib/capistrano/tasks' do
|
21
|
+
path = test_app_path.join('lib/capistrano/tasks')
|
22
|
+
expect(Dir.exists?(path)).to be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'creates the deploy file' do
|
26
|
+
file = test_app_path.join('config/deploy.rb')
|
27
|
+
expect(File.exists?(file)).to be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'creates the stage files' do
|
31
|
+
staging = test_app_path.join('config/deploy/staging.rb')
|
32
|
+
production = test_app_path.join('config/deploy/production.rb')
|
33
|
+
expect(File.exists?(staging)).to be_true
|
34
|
+
expect(File.exists?(production)).to be_true
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with STAGES' do
|
41
|
+
before :all do
|
42
|
+
create_test_app
|
43
|
+
Dir.chdir(test_app_path) do
|
44
|
+
%x[bundle exec cap install STAGES=qa,production]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'installation' do
|
49
|
+
|
50
|
+
it 'creates config/deploy' do
|
51
|
+
path = test_app_path.join('config/deploy')
|
52
|
+
expect(Dir.exists?(path)).to be_true
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'creates lib/capistrano/tasks' do
|
56
|
+
path = test_app_path.join('lib/capistrano/tasks')
|
57
|
+
expect(Dir.exists?(path)).to be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'creates the deploy file' do
|
61
|
+
file = test_app_path.join('config/deploy.rb')
|
62
|
+
expect(File.exists?(file)).to be_true
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'creates the stage files specified, not the defaults' do
|
66
|
+
qa = test_app_path.join('config/deploy/qa.rb')
|
67
|
+
production = test_app_path.join('config/deploy/production.rb')
|
68
|
+
staging = test_app_path.join('config/deploy/staging.rb')
|
69
|
+
expect(File.exists?(qa)).to be_true
|
70
|
+
expect(File.exists?(production)).to be_true
|
71
|
+
expect(File.exists?(staging)).to be_false
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Capistrano::Application do
|
4
|
+
|
5
|
+
it "provides a --trace option which enables SSHKit/NetSSH trace output"
|
6
|
+
|
7
|
+
it "provides a --format option which enables the choice of output formatting"
|
8
|
+
|
9
|
+
it "identifies itself as cap and not rake" do
|
10
|
+
pending "Waiting for: https://github.com/jimweirich/rake/pull/204"
|
11
|
+
out, _ = capture_io do
|
12
|
+
flags '--help', '-h'
|
13
|
+
end
|
14
|
+
out.should match(/\bcap [ -f capfile ]\b/)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "overrides the rake method, but still prints the rake version" do
|
18
|
+
out, _ = capture_io do
|
19
|
+
flags '--version', '-V'
|
20
|
+
end
|
21
|
+
out.should match(/\bCapistrano Version\b/)
|
22
|
+
out.should match(/\b#{Capistrano::VERSION}\b/)
|
23
|
+
out.should match(/\bRake Version\b/)
|
24
|
+
out.should match(/\b#{RAKEVERSION}\b/)
|
25
|
+
end
|
26
|
+
|
27
|
+
def flags(*sets)
|
28
|
+
sets.each do |set|
|
29
|
+
ARGV.clear
|
30
|
+
@exit = catch(:system_exit) { command_line(*set) }
|
31
|
+
end
|
32
|
+
yield(subject.options) if block_given?
|
33
|
+
end
|
34
|
+
|
35
|
+
def command_line(*options)
|
36
|
+
options.each { |opt| ARGV << opt }
|
37
|
+
def subject.exit(*args)
|
38
|
+
throw(:system_exit, :exit)
|
39
|
+
end
|
40
|
+
subject.instance_eval do
|
41
|
+
handle_options
|
42
|
+
end
|
43
|
+
subject.options
|
44
|
+
end
|
45
|
+
|
46
|
+
def capture_io
|
47
|
+
require 'stringio'
|
48
|
+
|
49
|
+
orig_stdout, orig_stderr = $stdout, $stderr
|
50
|
+
captured_stdout, captured_stderr = StringIO.new, StringIO.new
|
51
|
+
$stdout, $stderr = captured_stdout, captured_stderr
|
52
|
+
|
53
|
+
yield
|
54
|
+
|
55
|
+
return captured_stdout.string, captured_stderr.string
|
56
|
+
ensure
|
57
|
+
$stdout = orig_stdout
|
58
|
+
$stderr = orig_stderr
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -12,6 +12,14 @@ module Capistrano
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
describe 'adding roles' do
|
16
|
+
subject { server.add_roles([:things, :stuff]) }
|
17
|
+
it 'adds the roles' do
|
18
|
+
expect{subject}.to change{server.roles.size}.from(0).to(2)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
15
23
|
describe 'checking roles' do
|
16
24
|
subject { server.has_role?(:test) }
|
17
25
|
|
@@ -43,6 +51,89 @@ module Capistrano
|
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
54
|
+
describe 'identifying as primary' do
|
55
|
+
subject { server.primary }
|
56
|
+
context 'server is primary' do
|
57
|
+
before do
|
58
|
+
server.set(:primary, true)
|
59
|
+
end
|
60
|
+
it 'returns self' do
|
61
|
+
expect(subject).to eq server
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'server is not primary' do
|
66
|
+
it 'is falesy' do
|
67
|
+
expect(subject).to be_false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'assigning properties' do
|
73
|
+
|
74
|
+
before do
|
75
|
+
server.with(properties)
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'properties contains roles' do
|
79
|
+
let(:properties) { {roles: [:clouds]} }
|
80
|
+
|
81
|
+
it 'adds the roles' do
|
82
|
+
expect(server.roles.first).to eq :clouds
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'properties contains user' do
|
87
|
+
let(:properties) { {user: 'tomc'} }
|
88
|
+
|
89
|
+
it 'sets the user' do
|
90
|
+
expect(server.user).to eq 'tomc'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'properties contains port' do
|
95
|
+
let(:properties) { {port: 2222} }
|
96
|
+
|
97
|
+
it 'sets the port' do
|
98
|
+
expect(server.port).to eq 2222
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'properties contains key' do
|
103
|
+
let(:properties) { {key: '/key'} }
|
104
|
+
|
105
|
+
it 'adds the key' do
|
106
|
+
expect(server.keys).to include '/key'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'properties contains password' do
|
111
|
+
let(:properties) { {password: 'supersecret'} }
|
112
|
+
|
113
|
+
it 'adds the key' do
|
114
|
+
expect(server.password).to eq 'supersecret'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'new properties' do
|
119
|
+
let(:properties) { { webscales: 5 } }
|
120
|
+
|
121
|
+
it 'adds the properties' do
|
122
|
+
expect(server.properties.webscales).to eq 5
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'existing properties' do
|
127
|
+
let(:properties) { { webscales: 6 } }
|
128
|
+
|
129
|
+
it 'keeps the existing properties' do
|
130
|
+
expect(server.properties.webscales).to eq 6
|
131
|
+
server.properties.webscales = 5
|
132
|
+
expect(server.properties.webscales).to eq 5
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
46
137
|
end
|
47
138
|
end
|
48
139
|
end
|
@@ -6,11 +6,28 @@ module Capistrano
|
|
6
6
|
let(:servers) { Servers.new }
|
7
7
|
|
8
8
|
describe 'adding a role' do
|
9
|
-
subject { servers.add_role(:app, %w{1 2}) }
|
10
9
|
|
11
10
|
it 'adds two new server instances' do
|
12
|
-
expect{
|
11
|
+
expect{servers.add_role(:app, %w{1 2})}.
|
12
|
+
to change{servers.count}.from(0).to(2)
|
13
13
|
end
|
14
|
+
|
15
|
+
it 'handles de-duplification within roles' do
|
16
|
+
servers.add_role(:app, %w{1})
|
17
|
+
servers.add_role(:app, %w{1})
|
18
|
+
expect(servers.count).to eq 1
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'accepts instances of server objects' do
|
22
|
+
servers.add_role(:app, [Capistrano::Configuration::Server.new('example.net'), 'example.com'])
|
23
|
+
expect(servers.roles_for([:app]).length).to eq 2
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'accepts non-enumerable types' do
|
27
|
+
servers.add_role(:app, '1')
|
28
|
+
expect(servers.roles_for([:app]).count).to eq 1
|
29
|
+
end
|
30
|
+
|
14
31
|
end
|
15
32
|
|
16
33
|
describe 'adding a role to an existing server' do
|
@@ -22,6 +39,7 @@ module Capistrano
|
|
22
39
|
it 'adds new roles to existing servers' do
|
23
40
|
expect(servers.count).to eq 2
|
24
41
|
end
|
42
|
+
|
25
43
|
end
|
26
44
|
|
27
45
|
describe 'collecting server roles' do
|
@@ -35,20 +53,21 @@ module Capistrano
|
|
35
53
|
end
|
36
54
|
|
37
55
|
it 'returns an array of the roles' do
|
38
|
-
expect(servers.
|
39
|
-
expect(servers.
|
56
|
+
expect(servers.roles_for([:app]).collect(&:roles)).to eq [app, web_app, web_app]
|
57
|
+
expect(servers.roles_for([:web]).collect(&:roles)).to eq [web_app, web_app, web]
|
40
58
|
end
|
41
59
|
end
|
42
60
|
|
43
61
|
describe 'finding the primary server' do
|
44
|
-
it 'takes the first server
|
62
|
+
it 'takes the first server if none have the primary property' do
|
45
63
|
servers.add_role(:app, %w{1 2})
|
46
|
-
servers.fetch_primary(:app).hostname.should ==
|
64
|
+
servers.fetch_primary(:app).hostname.should == '1'
|
47
65
|
end
|
66
|
+
|
48
67
|
it 'takes the first server with the primary have the primary flag' do
|
49
68
|
servers.add_role(:app, %w{1 2})
|
50
69
|
servers.add_host('2', primary: true)
|
51
|
-
servers.fetch_primary(:app).hostname.should ==
|
70
|
+
servers.fetch_primary(:app).hostname.should == '2'
|
52
71
|
end
|
53
72
|
end
|
54
73
|
|
@@ -59,21 +78,70 @@ module Capistrano
|
|
59
78
|
end
|
60
79
|
|
61
80
|
it 'returns the correct app servers' do
|
62
|
-
expect(servers.
|
81
|
+
expect(servers.roles_for([:app]).map(&:hostname)).to eq %w{1 2}
|
63
82
|
end
|
64
83
|
|
65
84
|
it 'returns the correct web servers' do
|
66
|
-
expect(servers.
|
85
|
+
expect(servers.roles_for([:web]).map(&:hostname)).to eq %w{2 3}
|
67
86
|
end
|
68
87
|
|
69
88
|
it 'returns the correct app and web servers' do
|
70
|
-
expect(servers.
|
89
|
+
expect(servers.roles_for([:app, :web]).map(&:hostname)).to eq %w{1 2 3}
|
71
90
|
end
|
72
91
|
|
73
92
|
it 'returns all servers' do
|
74
|
-
expect(servers.
|
93
|
+
expect(servers.roles_for([:all]).map(&:hostname)).to eq %w{1 2 3}
|
75
94
|
end
|
76
95
|
end
|
96
|
+
|
97
|
+
describe 'adding a server' do
|
98
|
+
|
99
|
+
before do
|
100
|
+
servers.add_host('1', roles: [:app, 'web'], test: :value)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'can create a server with properties' do
|
104
|
+
expect(servers.roles_for([:app]).first.hostname).to eq '1'
|
105
|
+
expect(servers.roles_for([:web]).first.hostname).to eq '1'
|
106
|
+
expect(servers.roles_for([:all]).first.properties.test).to eq :value
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#roles' do
|
112
|
+
|
113
|
+
before do
|
114
|
+
servers.add_host('1', roles: :app, active: true)
|
115
|
+
servers.add_host('2', roles: :app)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'raises if the filter would remove all matching hosts' do
|
119
|
+
I18n.expects(:t)
|
120
|
+
expect { servers.roles_for([:app, select: :inactive]) }.to raise_error
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'can filter hosts by properties on the host object using symbol as shorthand' do
|
124
|
+
expect(servers.roles_for([:app, filter: :active]).length).to eq 1
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'can select hosts by properties on the host object using symbol as shorthand' do
|
128
|
+
expect(servers.roles_for([:app, select: :active]).length).to eq 1
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'can filter hosts by properties on the host using a regular proc' do
|
132
|
+
expect(servers.roles_for([:app, filter: lambda { |h| h.properties.active }]).length).to eq 1
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'can select hosts by properties on the host using a regular proc' do
|
136
|
+
expect(servers.roles_for([:app, select: lambda { |h| h.properties.active }]).length).to eq 1
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'raises if the regular proc filter would remove all matching hosts' do
|
140
|
+
I18n.expects(:t)
|
141
|
+
expect { servers.roles_for([:app, select: lambda { |h| h.properties.inactive }])}.to raise_error
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
77
145
|
end
|
78
146
|
end
|
79
147
|
end
|
@@ -18,7 +18,7 @@ module Capistrano
|
|
18
18
|
|
19
19
|
before do
|
20
20
|
Configuration::Servers.expects(:new).returns(servers)
|
21
|
-
servers.expects(:add_role).with(:app, %w{server1 server2})
|
21
|
+
servers.expects(:add_role).with(:app, %w{server1 server2}, {})
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'adds the role' do
|
@@ -75,6 +75,16 @@ module Capistrano
|
|
75
75
|
expect(config.fetch(:branch)).to eq question
|
76
76
|
end
|
77
77
|
end
|
78
|
-
end
|
79
78
|
|
79
|
+
describe 'setting the backend' do
|
80
|
+
it 'by default, is SSHKit' do
|
81
|
+
expect(config.backend).to eq SSHKit
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'can be set to another class' do
|
85
|
+
config.backend = :test
|
86
|
+
expect(config.backend).to eq :test
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
80
90
|
end
|
@@ -5,79 +5,6 @@ module Capistrano
|
|
5
5
|
|
6
6
|
describe Env do
|
7
7
|
|
8
|
-
let(:env) { Configuration.new }
|
9
|
-
|
10
|
-
describe '#role' do
|
11
|
-
|
12
|
-
it 'can add a role, with hosts' do
|
13
|
-
env.role(:app, %w{example.com})
|
14
|
-
env.roles_for(:app).first.hostname.should == "example.com"
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'handles de-duplification within roles' do
|
18
|
-
env.role(:app, %w{example.com})
|
19
|
-
env.role(:app, %w{example.com})
|
20
|
-
env.roles_for(:app).length.should == 1
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'accepts instances of server objects' do
|
24
|
-
pending
|
25
|
-
env.role(:app, [Capistrano::Configuration::Server.new('example.net'), 'example.com'])
|
26
|
-
env.roles_for(:app).length.should == 2
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'accepts non-enumerable types' do
|
30
|
-
env.role(:app, 'example.com')
|
31
|
-
env.roles_for(:app).length.should == 1
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#server' do
|
37
|
-
|
38
|
-
it "can create a server with properties" do
|
39
|
-
env.server('example.com', roles: [:app, "web"], my: :value)
|
40
|
-
env.roles_for(:app).first.hostname.should == 'example.com'
|
41
|
-
env.roles_for(:web).first.hostname.should == 'example.com'
|
42
|
-
env.roles_for(:all).first.properties.my.should == :value
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
describe '#roles' do
|
48
|
-
|
49
|
-
before do
|
50
|
-
env.server('example.com', roles: :app, active: true)
|
51
|
-
env.server('example.org', roles: :app)
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'raises if the filter would remove all matching hosts' do
|
55
|
-
pending
|
56
|
-
env.server('example.org', active: true)
|
57
|
-
lambda do
|
58
|
-
env.roles_for(:app, filter: lambda { |s| !s.properties.active })
|
59
|
-
end.should raise_error
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'can filter hosts by properties on the host object using symbol as shorthand' do
|
63
|
-
env.roles_for(:app, filter: :active).length.should == 1
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'can select hosts by properties on the host object using symbol as shorthand' do
|
67
|
-
env.roles_for(:app, select: :active).length.should == 1
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'can filter hosts by properties on the host using a regular proc' do
|
71
|
-
env.roles_for(:app, filter: lambda { |h| h.properties.active } ).length.should == 1
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'can select hosts by properties on the host using a regular proc' do
|
75
|
-
env.roles_for(:app, select: lambda { |h| h.properties.active } ).length.should == 1
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
8
|
end
|
81
|
-
|
82
9
|
end
|
83
10
|
end
|