capistrano 3.4.1 → 3.5.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.
- checksums.yaml +4 -4
- data/.gitignore +7 -5
- data/.rubocop.yml +49 -0
- data/.travis.yml +5 -4
- data/CHANGELOG.md +72 -9
- data/CONTRIBUTING.md +61 -93
- data/DEVELOPMENT.md +122 -0
- data/Gemfile +2 -2
- data/LICENSE.txt +1 -1
- data/README.md +121 -43
- data/RELEASING.md +16 -0
- data/Rakefile +4 -1
- data/bin/cap +1 -1
- data/capistrano.gemspec +16 -21
- data/features/doctor.feature +11 -0
- data/features/step_definitions/assertions.rb +17 -17
- data/features/step_definitions/cap_commands.rb +0 -1
- data/features/step_definitions/setup.rb +12 -8
- data/features/support/env.rb +5 -5
- data/features/support/remote_command_helpers.rb +8 -6
- data/features/support/vagrant_helpers.rb +5 -4
- data/issue_template.md +21 -0
- data/lib/Capfile +5 -1
- data/lib/capistrano/all.rb +9 -10
- data/lib/capistrano/application.rb +36 -26
- data/lib/capistrano/configuration.rb +56 -41
- data/lib/capistrano/configuration/empty_filter.rb +9 -0
- data/lib/capistrano/configuration/filter.rb +18 -47
- data/lib/capistrano/configuration/host_filter.rb +30 -0
- data/lib/capistrano/configuration/null_filter.rb +9 -0
- data/lib/capistrano/configuration/plugin_installer.rb +33 -0
- data/lib/capistrano/configuration/question.rb +10 -7
- data/lib/capistrano/configuration/role_filter.rb +30 -0
- data/lib/capistrano/configuration/server.rb +22 -23
- data/lib/capistrano/configuration/servers.rb +6 -7
- data/lib/capistrano/configuration/variables.rb +136 -0
- data/lib/capistrano/defaults.rb +13 -3
- data/lib/capistrano/deploy.rb +1 -1
- data/lib/capistrano/doctor.rb +5 -0
- data/lib/capistrano/doctor/environment_doctor.rb +19 -0
- data/lib/capistrano/doctor/gems_doctor.rb +45 -0
- data/lib/capistrano/doctor/output_helpers.rb +79 -0
- data/lib/capistrano/doctor/variables_doctor.rb +66 -0
- data/lib/capistrano/dotfile.rb +1 -2
- data/lib/capistrano/dsl.rb +12 -14
- data/lib/capistrano/dsl/env.rb +11 -42
- data/lib/capistrano/dsl/paths.rb +12 -13
- data/lib/capistrano/dsl/stages.rb +2 -4
- data/lib/capistrano/dsl/task_enhancements.rb +5 -7
- data/lib/capistrano/framework.rb +1 -1
- data/lib/capistrano/git.rb +17 -9
- data/lib/capistrano/hg.rb +4 -4
- data/lib/capistrano/i18n.rb +24 -24
- data/lib/capistrano/immutable_task.rb +29 -0
- data/lib/capistrano/install.rb +1 -1
- data/lib/capistrano/plugin.rb +95 -0
- data/lib/capistrano/scm.rb +7 -20
- data/lib/capistrano/setup.rb +19 -5
- data/lib/capistrano/svn.rb +9 -5
- data/lib/capistrano/tasks/console.rake +4 -8
- data/lib/capistrano/tasks/deploy.rake +75 -62
- data/lib/capistrano/tasks/doctor.rake +19 -0
- data/lib/capistrano/tasks/framework.rake +13 -14
- data/lib/capistrano/tasks/git.rake +10 -11
- data/lib/capistrano/tasks/hg.rake +7 -7
- data/lib/capistrano/tasks/install.rake +14 -15
- data/lib/capistrano/tasks/svn.rake +7 -7
- data/lib/capistrano/templates/Capfile +3 -3
- data/lib/capistrano/templates/deploy.rb.erb +6 -5
- data/lib/capistrano/upload_task.rb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/lib/capistrano/version_validator.rb +4 -6
- data/spec/integration/dsl_spec.rb +286 -239
- data/spec/integration_spec_helper.rb +3 -5
- data/spec/lib/capistrano/application_spec.rb +22 -14
- data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/filter_spec.rb +82 -84
- data/spec/lib/capistrano/configuration/host_filter_spec.rb +61 -0
- data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +12 -16
- data/spec/lib/capistrano/configuration/role_filter_spec.rb +64 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +102 -110
- data/spec/lib/capistrano/configuration/servers_spec.rb +124 -141
- data/spec/lib/capistrano/configuration_spec.rb +150 -61
- data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
- data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +61 -0
- data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
- data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +79 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +58 -50
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +62 -32
- data/spec/lib/capistrano/dsl_spec.rb +6 -8
- data/spec/lib/capistrano/git_spec.rb +35 -7
- data/spec/lib/capistrano/hg_spec.rb +14 -5
- data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
- data/spec/lib/capistrano/plugin_spec.rb +84 -0
- data/spec/lib/capistrano/scm_spec.rb +6 -7
- data/spec/lib/capistrano/svn_spec.rb +40 -14
- data/spec/lib/capistrano/upload_task_spec.rb +7 -7
- data/spec/lib/capistrano/version_validator_spec.rb +37 -45
- data/spec/lib/capistrano_spec.rb +2 -3
- data/spec/spec_helper.rb +8 -8
- data/spec/support/Vagrantfile +9 -10
- data/spec/support/tasks/database.rake +3 -3
- data/spec/support/tasks/fail.rake +4 -3
- data/spec/support/tasks/failed.rake +2 -2
- data/spec/support/tasks/plugin.rake +6 -0
- data/spec/support/tasks/root.rake +4 -4
- data/spec/support/test_app.rb +31 -30
- metadata +93 -14
@@ -1,14 +1,13 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe Capistrano::Application do
|
4
|
-
|
5
4
|
it "provides a --trace option which enables SSHKit/NetSSH trace output"
|
6
5
|
|
7
6
|
it "provides a --format option which enables the choice of output formatting"
|
8
7
|
|
9
8
|
let(:help_output) do
|
10
|
-
out,
|
11
|
-
flags
|
9
|
+
out, _err = capture_io do
|
10
|
+
flags "--help", "-h"
|
12
11
|
end
|
13
12
|
out
|
14
13
|
end
|
@@ -24,8 +23,8 @@ describe Capistrano::Application do
|
|
24
23
|
end
|
25
24
|
|
26
25
|
it "overrides the rake method, but still prints the rake version" do
|
27
|
-
out,
|
28
|
-
flags
|
26
|
+
out, _err = capture_io do
|
27
|
+
flags "--version", "-V"
|
29
28
|
end
|
30
29
|
expect(out).to match(/\bCapistrano Version\b/)
|
31
30
|
expect(out).to match(/\b#{Capistrano::VERSION}\b/)
|
@@ -34,13 +33,20 @@ describe Capistrano::Application do
|
|
34
33
|
end
|
35
34
|
|
36
35
|
it "overrides the rake method, and sets the sshkit_backend to SSHKit::Backend::Printer" do
|
37
|
-
|
38
|
-
flags
|
36
|
+
capture_io do
|
37
|
+
flags "--dry-run", "-n"
|
39
38
|
end
|
40
39
|
sshkit_backend = Capistrano::Configuration.fetch(:sshkit_backend)
|
41
40
|
expect(sshkit_backend).to eq(SSHKit::Backend::Printer)
|
42
41
|
end
|
43
42
|
|
43
|
+
it "enables printing all config variables on command line parameter" do
|
44
|
+
capture_io do
|
45
|
+
flags "--print-config-variables", "-p"
|
46
|
+
end
|
47
|
+
expect(Capistrano::Configuration.fetch(:print_config_variables)).to be true
|
48
|
+
end
|
49
|
+
|
44
50
|
def flags(*sets)
|
45
51
|
sets.each do |set|
|
46
52
|
ARGV.clear
|
@@ -51,7 +57,7 @@ describe Capistrano::Application do
|
|
51
57
|
|
52
58
|
def command_line(*options)
|
53
59
|
options.each { |opt| ARGV << opt }
|
54
|
-
|
60
|
+
subject.define_singleton_method(:exit) do |*_args|
|
55
61
|
throw(:system_exit, :exit)
|
56
62
|
end
|
57
63
|
subject.run
|
@@ -59,11 +65,14 @@ describe Capistrano::Application do
|
|
59
65
|
end
|
60
66
|
|
61
67
|
def capture_io
|
62
|
-
require
|
68
|
+
require "stringio"
|
63
69
|
|
64
|
-
orig_stdout
|
65
|
-
|
66
|
-
|
70
|
+
orig_stdout = $stdout
|
71
|
+
orig_stderr = $stderr
|
72
|
+
captured_stdout = StringIO.new
|
73
|
+
captured_stderr = StringIO.new
|
74
|
+
$stdout = captured_stdout
|
75
|
+
$stderr = captured_stderr
|
67
76
|
|
68
77
|
yield
|
69
78
|
|
@@ -72,5 +81,4 @@ describe Capistrano::Application do
|
|
72
81
|
$stdout = orig_stdout
|
73
82
|
$stderr = orig_stderr
|
74
83
|
end
|
75
|
-
|
76
84
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Configuration
|
5
|
+
describe EmptyFilter do
|
6
|
+
subject(:empty_filter) { EmptyFilter.new }
|
7
|
+
|
8
|
+
describe '#filter' do
|
9
|
+
let(:servers) { mock("servers") }
|
10
|
+
|
11
|
+
it "returns an empty array" do
|
12
|
+
expect(empty_filter.filter(servers)).to eq([])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,109 +1,107 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
module Capistrano
|
4
4
|
class Configuration
|
5
|
-
|
6
5
|
describe Filter do
|
7
|
-
let(:available)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
let(:available) do
|
7
|
+
[
|
8
|
+
Server.new("server1").add_roles([:web, :db]),
|
9
|
+
Server.new("server2").add_role(:web),
|
10
|
+
Server.new("server3").add_role(:redis),
|
11
|
+
Server.new("server4").add_role(:db),
|
12
|
+
Server.new("server5").add_role(:stageweb)
|
13
|
+
]
|
14
|
+
end
|
12
15
|
|
13
16
|
describe '#new' do
|
14
17
|
it "won't create an invalid type of filter" do
|
15
|
-
expect
|
16
|
-
|
17
|
-
|
18
|
+
expect do
|
19
|
+
Filter.new(:zarg)
|
20
|
+
end.to raise_error RuntimeError
|
18
21
|
end
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
context "with type :host" do
|
24
|
+
context "and no values" do
|
25
|
+
it "creates an EmptyFilter strategy" do
|
26
|
+
expect(Filter.new(:host).instance_variable_get(:@strategy)).to be_a(EmptyFilter)
|
27
|
+
end
|
28
|
+
end
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
|
30
|
+
context "and :all" do
|
31
|
+
it "creates an NullFilter strategy" do
|
32
|
+
expect(Filter.new(:host, :all).instance_variable_get(:@strategy)).to be_a(NullFilter)
|
33
|
+
end
|
34
|
+
end
|
27
35
|
|
28
|
-
|
29
|
-
|
30
|
-
|
36
|
+
context "and [:all]" do
|
37
|
+
it "creates an NullFilter strategy" do
|
38
|
+
expect(Filter.new(:host, [:all]).instance_variable_get(:@strategy)).to be_a(NullFilter)
|
39
|
+
end
|
40
|
+
end
|
31
41
|
|
32
|
-
|
33
|
-
|
42
|
+
context "and [:all]" do
|
43
|
+
it "creates an NullFilter strategy" do
|
44
|
+
expect(Filter.new(:host, "all").instance_variable_get(:@strategy)).to be_a(NullFilter)
|
45
|
+
end
|
46
|
+
end
|
34
47
|
end
|
35
48
|
|
36
|
-
|
49
|
+
context "with type :role" do
|
50
|
+
context "and no values" do
|
51
|
+
it "creates an EmptyFilter strategy" do
|
52
|
+
expect(Filter.new(:role).instance_variable_get(:@strategy)).to be_a(EmptyFilter)
|
53
|
+
end
|
54
|
+
end
|
37
55
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
it 'returns all hosts matching regexp' do
|
56
|
-
set = Filter.new(:host, 'server[13]$').filter(available)
|
57
|
-
expect(set.map(&:hostname)).to eq(%w{server1 server3})
|
58
|
-
end
|
59
|
-
it 'correctly identifies a regex with a comma in' do
|
60
|
-
set = Filter.new(:host, 'server\d{1,3}$').filter(available)
|
61
|
-
expect(set.map(&:hostname)).to eq(%w{server1 server2 server3 server4 server5})
|
56
|
+
context "and :all" do
|
57
|
+
it "creates an NullFilter strategy" do
|
58
|
+
expect(Filter.new(:role, :all).instance_variable_get(:@strategy)).to be_a(NullFilter)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "and [:all]" do
|
63
|
+
it "creates an NullFilter strategy" do
|
64
|
+
expect(Filter.new(:role, [:all]).instance_variable_get(:@strategy)).to be_a(NullFilter)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "and [:all]" do
|
69
|
+
it "creates an NullFilter strategy" do
|
70
|
+
expect(Filter.new(:role, "all").instance_variable_get(:@strategy)).to be_a(NullFilter)
|
71
|
+
end
|
72
|
+
end
|
62
73
|
end
|
63
74
|
end
|
64
75
|
|
65
|
-
describe '
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
expect(set.map(&:hostname)).to eq(%w{server1 server2})
|
75
|
-
end
|
76
|
-
it 'returns hosts in a single role' do
|
77
|
-
set = Filter.new(:role, [:web]).filter(available)
|
78
|
-
expect(set.size).to eq(2)
|
79
|
-
expect(set.map(&:hostname)).to eq(%w{server1 server2})
|
80
|
-
end
|
81
|
-
it 'returns hosts in multiple roles specified by a string' do
|
82
|
-
set = Filter.new(:role, 'web,db').filter(available)
|
83
|
-
expect(set.size).to eq(3)
|
84
|
-
expect(set.map(&:hostname)).to eq(%w{server1 server2 server4})
|
85
|
-
end
|
86
|
-
it 'returns hosts in multiple roles' do
|
87
|
-
set = Filter.new(:role, [:web, :db]).filter(available)
|
88
|
-
expect(set.size).to eq(3)
|
89
|
-
expect(set.map(&:hostname)).to eq(%w{server1 server2 server4})
|
76
|
+
describe '#filter' do
|
77
|
+
let(:strategy) { filter.instance_variable_get(:@strategy) }
|
78
|
+
let(:results) { mock("result") }
|
79
|
+
|
80
|
+
shared_examples 'it calls #filter on its strategy' do
|
81
|
+
it 'calls #filter on its strategy' do
|
82
|
+
strategy.expects(:filter).with(available).returns(results)
|
83
|
+
expect(filter.filter(available)).to eq(results)
|
84
|
+
end
|
90
85
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
86
|
+
|
87
|
+
context "for an empty filter" do
|
88
|
+
let(:filter) { Filter.new(:role) }
|
89
|
+
it_behaves_like 'it calls #filter on its strategy'
|
95
90
|
end
|
96
|
-
|
97
|
-
|
98
|
-
|
91
|
+
|
92
|
+
context "for a null filter" do
|
93
|
+
let(:filter) { Filter.new(:role, :all) }
|
94
|
+
it_behaves_like 'it calls #filter on its strategy'
|
99
95
|
end
|
100
|
-
|
101
|
-
|
102
|
-
|
96
|
+
|
97
|
+
context "for a role filter" do
|
98
|
+
let(:filter) { Filter.new(:role, "web") }
|
99
|
+
it_behaves_like 'it calls #filter on its strategy'
|
103
100
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
101
|
+
|
102
|
+
context "for a host filter" do
|
103
|
+
let(:filter) { Filter.new(:host, "server1") }
|
104
|
+
it_behaves_like 'it calls #filter on its strategy'
|
107
105
|
end
|
108
106
|
end
|
109
107
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Configuration
|
5
|
+
describe HostFilter do
|
6
|
+
subject(:host_filter) { HostFilter.new(values) }
|
7
|
+
|
8
|
+
let(:available) do
|
9
|
+
[Server.new("server1"),
|
10
|
+
Server.new("server2"),
|
11
|
+
Server.new("server3"),
|
12
|
+
Server.new("server4"),
|
13
|
+
Server.new("server5")]
|
14
|
+
end
|
15
|
+
|
16
|
+
shared_examples "it filters hosts correctly" do |expected|
|
17
|
+
it "filters correctly" do
|
18
|
+
set = host_filter.filter(available)
|
19
|
+
expect(set.map(&:hostname)).to eq(expected)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#filter' do
|
24
|
+
context "with a string" do
|
25
|
+
let(:values) { "server1" }
|
26
|
+
it_behaves_like "it filters hosts correctly", %w{server1}
|
27
|
+
|
28
|
+
context "and a single server" do
|
29
|
+
let(:available) { Server.new("server1") }
|
30
|
+
it_behaves_like "it filters hosts correctly", %w{server1}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with a comma separated string" do
|
35
|
+
let(:values) { "server1,server3" }
|
36
|
+
it_behaves_like "it filters hosts correctly", %w{server1 server3}
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with an array of strings" do
|
40
|
+
let(:values) { %w{server1 server3} }
|
41
|
+
it_behaves_like "it filters hosts correctly", %w{server1 server3}
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with a regexp" do
|
45
|
+
let(:values) { "server[13]$" }
|
46
|
+
it_behaves_like "it filters hosts correctly", %w{server1 server3}
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with a regexp with line boundaries" do
|
50
|
+
let(:values) { "^server" }
|
51
|
+
it_behaves_like "it filters hosts correctly", %w{server1 server2 server3 server4 server5}
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with a regexp with a comma" do
|
55
|
+
let(:values) { 'server\d{1,3}$' }
|
56
|
+
it_behaves_like "it filters hosts correctly", %w{server1 server2 server3 server4 server5}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
class Configuration
|
5
|
+
describe NullFilter do
|
6
|
+
subject(:null_filter) { NullFilter.new }
|
7
|
+
|
8
|
+
describe '#filter' do
|
9
|
+
let(:servers) { mock("servers") }
|
10
|
+
|
11
|
+
it "returns the servers passed in as arguments" do
|
12
|
+
expect(null_filter.filter(servers)).to eq(servers)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,38 +1,36 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
module Capistrano
|
4
4
|
class Configuration
|
5
|
-
|
6
5
|
describe Question do
|
7
|
-
|
8
6
|
let(:question) { Question.new(key, default, options) }
|
9
7
|
let(:question_without_echo) { Question.new(key, default, echo: false) }
|
10
8
|
let(:default) { :default }
|
11
9
|
let(:key) { :branch }
|
12
10
|
let(:options) { nil }
|
13
11
|
|
14
|
-
describe
|
15
|
-
it
|
12
|
+
describe ".new" do
|
13
|
+
it "takes a key, default, options" do
|
16
14
|
question
|
17
15
|
end
|
18
16
|
end
|
19
17
|
|
20
18
|
describe '#call' do
|
21
|
-
context
|
22
|
-
let(:branch) {
|
19
|
+
context "value is entered" do
|
20
|
+
let(:branch) { "branch" }
|
23
21
|
|
24
22
|
before do
|
25
|
-
$stdout.expects(:print).with(
|
23
|
+
$stdout.expects(:print).with("Please enter branch (default): ")
|
26
24
|
end
|
27
25
|
|
28
|
-
it
|
26
|
+
it "returns the echoed value" do
|
29
27
|
$stdin.expects(:gets).returns(branch)
|
30
28
|
$stdin.expects(:noecho).never
|
31
29
|
|
32
30
|
expect(question.call).to eq(branch)
|
33
31
|
end
|
34
32
|
|
35
|
-
it
|
33
|
+
it "returns the value but does not echo it" do
|
36
34
|
$stdin.expects(:noecho).returns(branch)
|
37
35
|
$stdout.expects(:print).with("\n")
|
38
36
|
|
@@ -40,21 +38,19 @@ module Capistrano
|
|
40
38
|
end
|
41
39
|
end
|
42
40
|
|
43
|
-
context
|
41
|
+
context "value is not entered" do
|
44
42
|
let(:branch) { default }
|
45
43
|
|
46
44
|
before do
|
47
|
-
$stdout.expects(:print).with(
|
48
|
-
$stdin.expects(:gets).returns(
|
45
|
+
$stdout.expects(:print).with("Please enter branch (default): ")
|
46
|
+
$stdin.expects(:gets).returns("")
|
49
47
|
end
|
50
48
|
|
51
|
-
|
52
|
-
it 'returns the default as the value' do
|
49
|
+
it "returns the default as the value" do
|
53
50
|
expect(question.call).to eq(branch)
|
54
51
|
end
|
55
52
|
end
|
56
53
|
end
|
57
54
|
end
|
58
|
-
|
59
55
|
end
|
60
56
|
end
|