capistrano 3.4.1 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -5
  3. data/.rubocop.yml +49 -0
  4. data/.travis.yml +5 -4
  5. data/CHANGELOG.md +72 -9
  6. data/CONTRIBUTING.md +61 -93
  7. data/DEVELOPMENT.md +122 -0
  8. data/Gemfile +2 -2
  9. data/LICENSE.txt +1 -1
  10. data/README.md +121 -43
  11. data/RELEASING.md +16 -0
  12. data/Rakefile +4 -1
  13. data/bin/cap +1 -1
  14. data/capistrano.gemspec +16 -21
  15. data/features/doctor.feature +11 -0
  16. data/features/step_definitions/assertions.rb +17 -17
  17. data/features/step_definitions/cap_commands.rb +0 -1
  18. data/features/step_definitions/setup.rb +12 -8
  19. data/features/support/env.rb +5 -5
  20. data/features/support/remote_command_helpers.rb +8 -6
  21. data/features/support/vagrant_helpers.rb +5 -4
  22. data/issue_template.md +21 -0
  23. data/lib/Capfile +5 -1
  24. data/lib/capistrano/all.rb +9 -10
  25. data/lib/capistrano/application.rb +36 -26
  26. data/lib/capistrano/configuration.rb +56 -41
  27. data/lib/capistrano/configuration/empty_filter.rb +9 -0
  28. data/lib/capistrano/configuration/filter.rb +18 -47
  29. data/lib/capistrano/configuration/host_filter.rb +30 -0
  30. data/lib/capistrano/configuration/null_filter.rb +9 -0
  31. data/lib/capistrano/configuration/plugin_installer.rb +33 -0
  32. data/lib/capistrano/configuration/question.rb +10 -7
  33. data/lib/capistrano/configuration/role_filter.rb +30 -0
  34. data/lib/capistrano/configuration/server.rb +22 -23
  35. data/lib/capistrano/configuration/servers.rb +6 -7
  36. data/lib/capistrano/configuration/variables.rb +136 -0
  37. data/lib/capistrano/defaults.rb +13 -3
  38. data/lib/capistrano/deploy.rb +1 -1
  39. data/lib/capistrano/doctor.rb +5 -0
  40. data/lib/capistrano/doctor/environment_doctor.rb +19 -0
  41. data/lib/capistrano/doctor/gems_doctor.rb +45 -0
  42. data/lib/capistrano/doctor/output_helpers.rb +79 -0
  43. data/lib/capistrano/doctor/variables_doctor.rb +66 -0
  44. data/lib/capistrano/dotfile.rb +1 -2
  45. data/lib/capistrano/dsl.rb +12 -14
  46. data/lib/capistrano/dsl/env.rb +11 -42
  47. data/lib/capistrano/dsl/paths.rb +12 -13
  48. data/lib/capistrano/dsl/stages.rb +2 -4
  49. data/lib/capistrano/dsl/task_enhancements.rb +5 -7
  50. data/lib/capistrano/framework.rb +1 -1
  51. data/lib/capistrano/git.rb +17 -9
  52. data/lib/capistrano/hg.rb +4 -4
  53. data/lib/capistrano/i18n.rb +24 -24
  54. data/lib/capistrano/immutable_task.rb +29 -0
  55. data/lib/capistrano/install.rb +1 -1
  56. data/lib/capistrano/plugin.rb +95 -0
  57. data/lib/capistrano/scm.rb +7 -20
  58. data/lib/capistrano/setup.rb +19 -5
  59. data/lib/capistrano/svn.rb +9 -5
  60. data/lib/capistrano/tasks/console.rake +4 -8
  61. data/lib/capistrano/tasks/deploy.rake +75 -62
  62. data/lib/capistrano/tasks/doctor.rake +19 -0
  63. data/lib/capistrano/tasks/framework.rake +13 -14
  64. data/lib/capistrano/tasks/git.rake +10 -11
  65. data/lib/capistrano/tasks/hg.rake +7 -7
  66. data/lib/capistrano/tasks/install.rake +14 -15
  67. data/lib/capistrano/tasks/svn.rake +7 -7
  68. data/lib/capistrano/templates/Capfile +3 -3
  69. data/lib/capistrano/templates/deploy.rb.erb +6 -5
  70. data/lib/capistrano/upload_task.rb +1 -1
  71. data/lib/capistrano/version.rb +1 -1
  72. data/lib/capistrano/version_validator.rb +4 -6
  73. data/spec/integration/dsl_spec.rb +286 -239
  74. data/spec/integration_spec_helper.rb +3 -5
  75. data/spec/lib/capistrano/application_spec.rb +22 -14
  76. data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
  77. data/spec/lib/capistrano/configuration/filter_spec.rb +82 -84
  78. data/spec/lib/capistrano/configuration/host_filter_spec.rb +61 -0
  79. data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
  80. data/spec/lib/capistrano/configuration/question_spec.rb +12 -16
  81. data/spec/lib/capistrano/configuration/role_filter_spec.rb +64 -0
  82. data/spec/lib/capistrano/configuration/server_spec.rb +102 -110
  83. data/spec/lib/capistrano/configuration/servers_spec.rb +124 -141
  84. data/spec/lib/capistrano/configuration_spec.rb +150 -61
  85. data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
  86. data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +61 -0
  87. data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
  88. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +79 -0
  89. data/spec/lib/capistrano/dsl/paths_spec.rb +58 -50
  90. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +62 -32
  91. data/spec/lib/capistrano/dsl_spec.rb +6 -8
  92. data/spec/lib/capistrano/git_spec.rb +35 -7
  93. data/spec/lib/capistrano/hg_spec.rb +14 -5
  94. data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
  95. data/spec/lib/capistrano/plugin_spec.rb +84 -0
  96. data/spec/lib/capistrano/scm_spec.rb +6 -7
  97. data/spec/lib/capistrano/svn_spec.rb +40 -14
  98. data/spec/lib/capistrano/upload_task_spec.rb +7 -7
  99. data/spec/lib/capistrano/version_validator_spec.rb +37 -45
  100. data/spec/lib/capistrano_spec.rb +2 -3
  101. data/spec/spec_helper.rb +8 -8
  102. data/spec/support/Vagrantfile +9 -10
  103. data/spec/support/tasks/database.rake +3 -3
  104. data/spec/support/tasks/fail.rake +4 -3
  105. data/spec/support/tasks/failed.rake +2 -2
  106. data/spec/support/tasks/plugin.rake +6 -0
  107. data/spec/support/tasks/root.rake +4 -4
  108. data/spec/support/test_app.rb +31 -30
  109. metadata +93 -14
@@ -0,0 +1,64 @@
1
+ require "spec_helper"
2
+
3
+ module Capistrano
4
+ class Configuration
5
+ describe RoleFilter do
6
+ subject(:role_filter) { RoleFilter.new(values) }
7
+
8
+ let(:available) do
9
+ [
10
+ Server.new("server1").add_roles([:web, :db]),
11
+ Server.new("server2").add_role(:web),
12
+ Server.new("server3").add_role(:redis),
13
+ Server.new("server4").add_role(:db),
14
+ Server.new("server5").add_role(:stageweb)
15
+ ]
16
+ end
17
+
18
+ shared_examples "it filters roles correctly" do |expected_size, expected|
19
+ it "filters correctly" do
20
+ set = role_filter.filter(available)
21
+ expect(set.size).to eq(expected_size)
22
+ expect(set.map(&:hostname)).to eq(expected)
23
+ end
24
+ end
25
+
26
+ describe '#filter' do
27
+ context "with a single role string" do
28
+ let(:values) { "web" }
29
+ it_behaves_like "it filters roles correctly", 2, %w{server1 server2}
30
+ end
31
+
32
+ context "with a single role" do
33
+ let(:values) { [:web] }
34
+ it_behaves_like "it filters roles correctly", 2, %w{server1 server2}
35
+ end
36
+
37
+ context "with multiple roles in a string" do
38
+ let(:values) { "web,db" }
39
+ it_behaves_like "it filters roles correctly", 3, %w{server1 server2 server4}
40
+ end
41
+
42
+ context "with multiple roles" do
43
+ let(:values) { [:web, :db] }
44
+ it_behaves_like "it filters roles correctly", 3, %w{server1 server2 server4}
45
+ end
46
+
47
+ context "with a regex" do
48
+ let(:values) { /red/ }
49
+ it_behaves_like "it filters roles correctly", 1, %w{server3}
50
+ end
51
+
52
+ context "with a regex string" do
53
+ let(:values) { "/red|web/" }
54
+ it_behaves_like "it filters roles correctly", 4, %w{server1 server2 server3 server5}
55
+ end
56
+
57
+ context "with both a string and regex" do
58
+ let(:values) { "db,/red/" }
59
+ it_behaves_like "it filters roles correctly", 3, %w{server1 server3 server4}
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,141 +1,139 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  module Capistrano
4
4
  class Configuration
5
5
  describe Server do
6
- let(:server) { Server.new('root@hostname:1234') }
6
+ let(:server) { Server.new("root@hostname:1234") }
7
7
 
8
- describe 'adding a role' do
8
+ describe "adding a role" do
9
9
  subject { server.add_role(:test) }
10
- it 'adds the role' do
11
- expect{subject}.to change{server.roles.size}.from(0).to(1)
10
+ it "adds the role" do
11
+ expect { subject }.to change { server.roles.size }.from(0).to(1)
12
12
  end
13
13
  end
14
14
 
15
- describe 'adding roles' do
15
+ describe "adding roles" do
16
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)
17
+ it "adds the roles" do
18
+ expect { subject }.to change { server.roles.size }.from(0).to(2)
19
19
  end
20
20
  end
21
21
 
22
-
23
- describe 'checking roles' do
22
+ describe "checking roles" do
24
23
  subject { server.has_role?(:test) }
25
24
 
26
25
  before do
27
26
  server.add_role(:test)
28
27
  end
29
28
 
30
- it 'adds the role' do
29
+ it "adds the role" do
31
30
  expect(subject).to be_truthy
32
31
  end
33
32
  end
34
33
 
35
- describe 'comparing identity' do
34
+ describe "comparing identity" do
36
35
  subject { server.hostname == Server[hostname].hostname }
37
36
 
38
- context 'with the same user, hostname and port' do
39
- let(:hostname) { 'root@hostname:1234' }
37
+ context "with the same user, hostname and port" do
38
+ let(:hostname) { "root@hostname:1234" }
40
39
  it { expect(subject).to be_truthy }
41
40
  end
42
41
 
43
- context 'with a different user' do
44
- let(:hostname) { 'deployer@hostname:1234' }
42
+ context "with a different user" do
43
+ let(:hostname) { "deployer@hostname:1234" }
45
44
  it { expect(subject).to be_truthy }
46
45
  end
47
46
 
48
- context 'with a different port' do
49
- let(:hostname) { 'root@hostname:5678' }
47
+ context "with a different port" do
48
+ let(:hostname) { "root@hostname:5678" }
50
49
  it { expect(subject).to be_truthy }
51
50
  end
52
51
 
53
- context 'with a different hostname' do
54
- let(:hostname) { 'root@otherserver:1234' }
52
+ context "with a different hostname" do
53
+ let(:hostname) { "root@otherserver:1234" }
55
54
  it { expect(subject).to be_falsey }
56
55
  end
57
56
  end
58
57
 
59
- describe 'identifying as primary' do
58
+ describe "identifying as primary" do
60
59
  subject { server.primary }
61
- context 'server is primary' do
60
+ context "server is primary" do
62
61
  before do
63
62
  server.set(:primary, true)
64
63
  end
65
- it 'returns self' do
64
+ it "returns self" do
66
65
  expect(subject).to eq server
67
66
  end
68
67
  end
69
68
 
70
- context 'server is not primary' do
71
- it 'is falesy' do
69
+ context "server is not primary" do
70
+ it "is falesy" do
72
71
  expect(subject).to be_falsey
73
72
  end
74
73
  end
75
74
  end
76
75
 
77
- describe 'assigning properties' do
78
-
76
+ describe "assigning properties" do
79
77
  before do
80
78
  server.with(properties)
81
79
  end
82
80
 
83
- context 'properties contains roles' do
84
- let(:properties) { {roles: [:clouds]} }
81
+ context "properties contains roles" do
82
+ let(:properties) { { roles: [:clouds] } }
85
83
 
86
- it 'adds the roles' do
84
+ it "adds the roles" do
87
85
  expect(server.roles.first).to eq :clouds
88
86
  end
89
87
  end
90
88
 
91
- context 'properties contains user' do
92
- let(:properties) { {user: 'tomc'} }
89
+ context "properties contains user" do
90
+ let(:properties) { { user: "tomc" } }
93
91
 
94
- it 'sets the user' do
95
- expect(server.user).to eq 'tomc'
92
+ it "sets the user" do
93
+ expect(server.user).to eq "tomc"
96
94
  end
97
95
 
98
- it 'sets the netssh_options user' do
99
- expect(server.netssh_options[:user]).to eq 'tomc'
96
+ it "sets the netssh_options user" do
97
+ expect(server.netssh_options[:user]).to eq "tomc"
100
98
  end
101
99
  end
102
100
 
103
- context 'properties contains port' do
104
- let(:properties) { {port: 2222} }
101
+ context "properties contains port" do
102
+ let(:properties) { { port: 2222 } }
105
103
 
106
- it 'sets the port' do
104
+ it "sets the port" do
107
105
  expect(server.port).to eq 2222
108
106
  end
109
107
  end
110
108
 
111
- context 'properties contains key' do
112
- let(:properties) { {key: '/key'} }
109
+ context "properties contains key" do
110
+ let(:properties) { { key: "/key" } }
113
111
 
114
- it 'adds the key' do
115
- expect(server.keys).to include '/key'
112
+ it "adds the key" do
113
+ expect(server.keys).to include "/key"
116
114
  end
117
115
  end
118
116
 
119
- context 'properties contains password' do
120
- let(:properties) { {password: 'supersecret'} }
117
+ context "properties contains password" do
118
+ let(:properties) { { password: "supersecret" } }
121
119
 
122
- it 'adds the key' do
123
- expect(server.password).to eq 'supersecret'
120
+ it "adds the key" do
121
+ expect(server.password).to eq "supersecret"
124
122
  end
125
123
  end
126
124
 
127
- context 'new properties' do
125
+ context "new properties" do
128
126
  let(:properties) { { webscales: 5 } }
129
127
 
130
- it 'adds the properties' do
128
+ it "adds the properties" do
131
129
  expect(server.properties.webscales).to eq 5
132
130
  end
133
131
  end
134
132
 
135
- context 'existing properties' do
133
+ context "existing properties" do
136
134
  let(:properties) { { webscales: 6 } }
137
135
 
138
- it 'keeps the existing properties' do
136
+ it "keeps the existing properties" do
139
137
  expect(server.properties.webscales).to eq 6
140
138
  server.properties.webscales = 5
141
139
  expect(server.properties.webscales).to eq 5
@@ -152,128 +150,123 @@ module Capistrano
152
150
  server.properties.active = true
153
151
  end
154
152
 
155
- context 'options are empty' do
153
+ context "options are empty" do
156
154
  it { expect(subject).to be_truthy }
157
155
  end
158
156
 
159
- context 'value is a symbol' do
160
- context 'value matches server property' do
161
-
162
- context 'with :filter' do
163
- let(:options) { { filter: :active }}
157
+ context "value is a symbol" do
158
+ context "value matches server property" do
159
+ context "with :filter" do
160
+ let(:options) { { filter: :active } }
164
161
  it { expect(subject).to be_truthy }
165
162
  end
166
163
 
167
- context 'with :select' do
168
- let(:options) { { select: :active }}
164
+ context "with :select" do
165
+ let(:options) { { select: :active } }
169
166
  it { expect(subject).to be_truthy }
170
167
  end
171
168
 
172
- context 'with :exclude' do
173
- let(:options) { { exclude: :active }}
169
+ context "with :exclude" do
170
+ let(:options) { { exclude: :active } }
174
171
  it { expect(subject).to be_falsey }
175
172
  end
176
173
  end
177
174
 
178
- context 'value does not match server properly' do
179
- context 'with :active true' do
180
- let(:options) { { active: true }}
175
+ context "value does not match server properly" do
176
+ context "with :active true" do
177
+ let(:options) { { active: true } }
181
178
  it { expect(subject).to be_truthy }
182
179
  end
183
180
 
184
- context 'with :active false' do
185
- let(:options) { { active: false }}
181
+ context "with :active false" do
182
+ let(:options) { { active: false } }
186
183
  it { expect(subject).to be_falsey }
187
184
  end
188
185
  end
189
186
 
190
- context 'value does not match server properly' do
191
- context 'with :filter' do
192
- let(:options) { { filter: :inactive }}
187
+ context "value does not match server properly" do
188
+ context "with :filter" do
189
+ let(:options) { { filter: :inactive } }
193
190
  it { expect(subject).to be_falsey }
194
191
  end
195
192
 
196
- context 'with :select' do
197
- let(:options) { { select: :inactive }}
193
+ context "with :select" do
194
+ let(:options) { { select: :inactive } }
198
195
  it { expect(subject).to be_falsey }
199
196
  end
200
197
 
201
- context 'with :exclude' do
202
- let(:options) { { exclude: :inactive }}
198
+ context "with :exclude" do
199
+ let(:options) { { exclude: :inactive } }
203
200
  it { expect(subject).to be_truthy }
204
201
  end
205
202
  end
206
203
  end
207
204
 
208
- context 'key is a property' do
209
- context 'with :active true' do
210
- let(:options) { { active: true }}
205
+ context "key is a property" do
206
+ context "with :active true" do
207
+ let(:options) { { active: true } }
211
208
  it { expect(subject).to be_truthy }
212
209
  end
213
210
 
214
- context 'with :active false' do
215
- let(:options) { { active: false }}
211
+ context "with :active false" do
212
+ let(:options) { { active: false } }
216
213
  it { expect(subject).to be_falsey }
217
214
  end
218
215
  end
219
216
 
220
- context 'value is a proc' do
221
- context 'value matches server property' do
222
-
223
- context 'with :filter' do
217
+ context "value is a proc" do
218
+ context "value matches server property" do
219
+ context "with :filter" do
224
220
  let(:options) { { filter: ->(s) { s.properties.active } } }
225
221
  it { expect(subject).to be_truthy }
226
222
  end
227
223
 
228
- context 'with :select' do
224
+ context "with :select" do
229
225
  let(:options) { { select: ->(s) { s.properties.active } } }
230
226
  it { expect(subject).to be_truthy }
231
227
  end
232
228
 
233
- context 'with :exclude' do
229
+ context "with :exclude" do
234
230
  let(:options) { { exclude: ->(s) { s.properties.active } } }
235
231
  it { expect(subject).to be_falsey }
236
232
  end
237
-
238
233
  end
239
234
 
240
- context 'value does not match server properly' do
241
- context 'with :filter' do
235
+ context "value does not match server properly" do
236
+ context "with :filter" do
242
237
  let(:options) { { filter: ->(s) { s.properties.inactive } } }
243
238
  it { expect(subject).to be_falsey }
244
239
  end
245
240
 
246
- context 'with :select' do
241
+ context "with :select" do
247
242
  let(:options) { { select: ->(s) { s.properties.inactive } } }
248
243
  it { expect(subject).to be_falsey }
249
244
  end
250
245
 
251
- context 'with :exclude' do
246
+ context "with :exclude" do
252
247
  let(:options) { { exclude: ->(s) { s.properties.inactive } } }
253
248
  it { expect(subject).to be_truthy }
254
249
  end
255
-
256
250
  end
257
251
  end
258
-
259
252
  end
260
253
 
261
- describe 'assign ssh_options' do
262
- let(:server) { Server.new('user_name@hostname') }
254
+ describe "assign ssh_options" do
255
+ let(:server) { Server.new("user_name@hostname") }
263
256
 
264
- context 'defaults' do
265
- it 'forward agent' do
257
+ context "defaults" do
258
+ it "forward agent" do
266
259
  expect(server.netssh_options[:forward_agent]).to eq true
267
260
  end
268
- it 'contains user' do
269
- expect(server.netssh_options[:user]).to eq 'user_name'
261
+ it "contains user" do
262
+ expect(server.netssh_options[:user]).to eq "user_name"
270
263
  end
271
264
  end
272
265
 
273
- context 'custom' do
266
+ context "custom" do
274
267
  let(:properties) do
275
268
  { ssh_options: {
276
- user: 'another_user',
269
+ user: "another_user",
277
270
  keys: %w(/home/another_user/.ssh/id_rsa),
278
271
  forward_agent: false,
279
272
  auth_methods: %w(publickey password) } }
@@ -283,31 +276,30 @@ module Capistrano
283
276
  server.with(properties)
284
277
  end
285
278
 
286
- it 'not forward agent' do
279
+ it "not forward agent" do
287
280
  expect(server.netssh_options[:forward_agent]).to eq false
288
281
  end
289
- it 'contains correct user' do
290
- expect(server.netssh_options[:user]).to eq 'another_user'
282
+ it "contains correct user" do
283
+ expect(server.netssh_options[:user]).to eq "another_user"
291
284
  end
292
- it 'does not affect server user in host' do
293
- expect(server.user).to eq 'user_name'
285
+ it "does not affect server user in host" do
286
+ expect(server.user).to eq "user_name"
294
287
  end
295
- it 'contains keys' do
288
+ it "contains keys" do
296
289
  expect(server.netssh_options[:keys]).to eq %w(/home/another_user/.ssh/id_rsa)
297
290
  end
298
- it 'contains auth_methods' do
291
+ it "contains auth_methods" do
299
292
  expect(server.netssh_options[:auth_methods]).to eq %w(publickey password)
300
293
  end
301
294
  end
302
-
303
295
  end
304
296
 
305
297
  describe ".[]" do
306
- it 'creates a server if its argument is not already a server' do
307
- expect(Server['hostname:1234']).to be_a Server
298
+ it "creates a server if its argument is not already a server" do
299
+ expect(Server["hostname:1234"]).to be_a Server
308
300
  end
309
301
 
310
- it 'returns its argument if it is already a server' do
302
+ it "returns its argument if it is already a server" do
311
303
  expect(Server[server]).to be server
312
304
  end
313
305
  end