capistrano 3.4.0 → 3.17.1

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 (138) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +129 -0
  3. data/.github/issue_template.md +19 -0
  4. data/.github/pull_request_template.md +22 -0
  5. data/.github/release-drafter.yml +17 -0
  6. data/.github/workflows/push.yml +12 -0
  7. data/.gitignore +8 -5
  8. data/.rubocop.yml +62 -0
  9. data/CHANGELOG.md +1 -307
  10. data/CONTRIBUTING.md +63 -93
  11. data/DEVELOPMENT.md +127 -0
  12. data/Dangerfile +1 -0
  13. data/Gemfile +40 -3
  14. data/LICENSE.txt +1 -1
  15. data/README.md +127 -44
  16. data/RELEASING.md +17 -0
  17. data/Rakefile +13 -2
  18. data/UPGRADING-3.7.md +86 -0
  19. data/bin/cap +1 -1
  20. data/capistrano.gemspec +21 -24
  21. data/features/deploy.feature +35 -1
  22. data/features/doctor.feature +11 -0
  23. data/features/installation.feature +8 -3
  24. data/features/stage_failure.feature +9 -0
  25. data/features/step_definitions/assertions.rb +51 -18
  26. data/features/step_definitions/cap_commands.rb +9 -0
  27. data/features/step_definitions/setup.rb +53 -9
  28. data/features/subdirectory.feature +9 -0
  29. data/features/support/env.rb +5 -5
  30. data/features/support/remote_command_helpers.rb +12 -6
  31. data/features/support/vagrant_helpers.rb +17 -11
  32. data/lib/Capfile +1 -1
  33. data/lib/capistrano/all.rb +10 -10
  34. data/lib/capistrano/application.rb +47 -34
  35. data/lib/capistrano/configuration/empty_filter.rb +9 -0
  36. data/lib/capistrano/configuration/filter.rb +17 -47
  37. data/lib/capistrano/configuration/host_filter.rb +29 -0
  38. data/lib/capistrano/configuration/null_filter.rb +9 -0
  39. data/lib/capistrano/configuration/plugin_installer.rb +51 -0
  40. data/lib/capistrano/configuration/question.rb +31 -9
  41. data/lib/capistrano/configuration/role_filter.rb +29 -0
  42. data/lib/capistrano/configuration/scm_resolver.rb +149 -0
  43. data/lib/capistrano/configuration/server.rb +29 -23
  44. data/lib/capistrano/configuration/servers.rb +21 -14
  45. data/lib/capistrano/configuration/validated_variables.rb +110 -0
  46. data/lib/capistrano/configuration/variables.rb +112 -0
  47. data/lib/capistrano/configuration.rb +91 -44
  48. data/lib/capistrano/defaults.rb +26 -4
  49. data/lib/capistrano/deploy.rb +1 -1
  50. data/lib/capistrano/doctor/environment_doctor.rb +19 -0
  51. data/lib/capistrano/doctor/gems_doctor.rb +45 -0
  52. data/lib/capistrano/doctor/output_helpers.rb +79 -0
  53. data/lib/capistrano/doctor/servers_doctor.rb +105 -0
  54. data/lib/capistrano/doctor/variables_doctor.rb +74 -0
  55. data/lib/capistrano/doctor.rb +6 -0
  56. data/lib/capistrano/dotfile.rb +1 -2
  57. data/lib/capistrano/dsl/env.rb +9 -47
  58. data/lib/capistrano/dsl/paths.rb +11 -25
  59. data/lib/capistrano/dsl/stages.rb +14 -2
  60. data/lib/capistrano/dsl/task_enhancements.rb +7 -12
  61. data/lib/capistrano/dsl.rb +47 -16
  62. data/lib/capistrano/framework.rb +1 -1
  63. data/lib/capistrano/i18n.rb +32 -24
  64. data/lib/capistrano/immutable_task.rb +30 -0
  65. data/lib/capistrano/install.rb +1 -1
  66. data/lib/capistrano/plugin.rb +95 -0
  67. data/lib/capistrano/proc_helpers.rb +13 -0
  68. data/lib/capistrano/scm/git.rb +100 -0
  69. data/lib/capistrano/scm/hg.rb +55 -0
  70. data/lib/capistrano/scm/plugin.rb +13 -0
  71. data/lib/capistrano/scm/svn.rb +56 -0
  72. data/lib/capistrano/scm/tasks/git.rake +73 -0
  73. data/lib/capistrano/scm/tasks/hg.rake +53 -0
  74. data/lib/capistrano/scm/tasks/svn.rake +53 -0
  75. data/lib/capistrano/scm.rb +7 -20
  76. data/lib/capistrano/setup.rb +20 -6
  77. data/lib/capistrano/tasks/console.rake +4 -8
  78. data/lib/capistrano/tasks/deploy.rake +105 -73
  79. data/lib/capistrano/tasks/doctor.rake +24 -0
  80. data/lib/capistrano/tasks/framework.rake +13 -14
  81. data/lib/capistrano/tasks/install.rake +14 -15
  82. data/lib/capistrano/templates/Capfile +21 -10
  83. data/lib/capistrano/templates/deploy.rb.erb +17 -26
  84. data/lib/capistrano/templates/stage.rb.erb +9 -9
  85. data/lib/capistrano/upload_task.rb +1 -1
  86. data/lib/capistrano/version.rb +1 -1
  87. data/lib/capistrano/version_validator.rb +5 -10
  88. data/spec/integration/dsl_spec.rb +289 -240
  89. data/spec/integration_spec_helper.rb +3 -5
  90. data/spec/lib/capistrano/application_spec.rb +23 -39
  91. data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
  92. data/spec/lib/capistrano/configuration/filter_spec.rb +83 -85
  93. data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
  94. data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
  95. data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
  96. data/spec/lib/capistrano/configuration/question_spec.rb +58 -26
  97. data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
  98. data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +55 -0
  99. data/spec/lib/capistrano/configuration/server_spec.rb +106 -113
  100. data/spec/lib/capistrano/configuration/servers_spec.rb +129 -145
  101. data/spec/lib/capistrano/configuration_spec.rb +224 -63
  102. data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
  103. data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
  104. data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
  105. data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
  106. data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
  107. data/spec/lib/capistrano/dsl/paths_spec.rb +97 -59
  108. data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +57 -37
  109. data/spec/lib/capistrano/dsl_spec.rb +84 -11
  110. data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
  111. data/spec/lib/capistrano/plugin_spec.rb +84 -0
  112. data/spec/lib/capistrano/scm/git_spec.rb +184 -0
  113. data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
  114. data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
  115. data/spec/lib/capistrano/scm_spec.rb +7 -8
  116. data/spec/lib/capistrano/upload_task_spec.rb +7 -7
  117. data/spec/lib/capistrano/version_validator_spec.rb +61 -46
  118. data/spec/lib/capistrano_spec.rb +2 -3
  119. data/spec/spec_helper.rb +21 -8
  120. data/spec/support/Vagrantfile +9 -10
  121. data/spec/support/tasks/database.rake +3 -3
  122. data/spec/support/tasks/fail.rake +4 -3
  123. data/spec/support/tasks/failed.rake +2 -2
  124. data/spec/support/tasks/plugin.rake +6 -0
  125. data/spec/support/tasks/root.rake +4 -4
  126. data/spec/support/test_app.rb +64 -39
  127. metadata +100 -55
  128. data/.travis.yml +0 -13
  129. data/features/remote_file_task.feature +0 -14
  130. data/lib/capistrano/git.rb +0 -46
  131. data/lib/capistrano/hg.rb +0 -43
  132. data/lib/capistrano/svn.rb +0 -38
  133. data/lib/capistrano/tasks/git.rake +0 -81
  134. data/lib/capistrano/tasks/hg.rake +0 -52
  135. data/lib/capistrano/tasks/svn.rake +0 -52
  136. data/spec/lib/capistrano/git_spec.rb +0 -81
  137. data/spec/lib/capistrano/hg_spec.rb +0 -81
  138. data/spec/lib/capistrano/svn_spec.rb +0 -79
@@ -1,7 +1,5 @@
1
- require 'spec_helper'
2
- require 'support/test_app'
3
- require 'support/matchers'
1
+ require "spec_helper"
2
+ require "support/test_app"
3
+ require "support/matchers"
4
4
 
5
5
  include TestApp
6
-
7
-
@@ -1,46 +1,46 @@
1
- require 'spec_helper'
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
- let(:help_output) do
10
- out, _ = capture_io do
11
- flags '--help', '-h'
12
- end
13
- out
14
- end
15
-
16
- it "displays documentation URL as help banner" do
17
- expect(help_output.lines.first).to match(/capistranorb.com/)
8
+ it "displays documentation URL as help banner", capture_io: true do
9
+ flags "--help", "-h"
10
+ expect($stdout.string.each_line.first).to match(/capistranorb.com/)
18
11
  end
19
12
 
20
13
  %w(quiet silent verbose).each do |switch|
21
- it "doesn't include --#{switch} in help" do
22
- expect(help_output).not_to match(/--#{switch}/)
14
+ it "doesn't include --#{switch} in help", capture_io: true do
15
+ flags "--help", "-h"
16
+ expect($stdout.string).not_to match(/--#{switch}/)
23
17
  end
24
18
  end
25
19
 
26
- it "overrides the rake method, but still prints the rake version" do
27
- out, _ = capture_io do
28
- flags '--version', '-V'
29
- end
20
+ it "overrides the rake method, but still prints the rake version", capture_io: true do
21
+ flags "--version", "-V"
22
+ out = $stdout.string
30
23
  expect(out).to match(/\bCapistrano Version\b/)
31
24
  expect(out).to match(/\b#{Capistrano::VERSION}\b/)
32
25
  expect(out).to match(/\bRake Version\b/)
33
- expect(out).to match(/\b#{RAKEVERSION}\b/)
26
+ expect(out).to match(/\b#{Rake::VERSION}\b/)
34
27
  end
35
28
 
36
- it "overrides the rake method, and sets the sshkit_backend to SSHKit::Backend::Printer" do
37
- out, _ = capture_io do
38
- flags '--dry-run', '-n'
39
- end
29
+ it "overrides the rake method, and sets the sshkit_backend to SSHKit::Backend::Printer", capture_io: true do
30
+ flags "--dry-run", "-n"
40
31
  sshkit_backend = Capistrano::Configuration.fetch(:sshkit_backend)
41
32
  expect(sshkit_backend).to eq(SSHKit::Backend::Printer)
42
33
  end
43
34
 
35
+ it "enables printing all config variables on command line parameter", capture_io: true do
36
+ begin
37
+ flags "--print-config-variables", "-p"
38
+ expect(Capistrano::Configuration.fetch(:print_config_variables)).to be true
39
+ ensure
40
+ Capistrano::Configuration.reset!
41
+ end
42
+ end
43
+
44
44
  def flags(*sets)
45
45
  sets.each do |set|
46
46
  ARGV.clear
@@ -51,26 +51,10 @@ describe Capistrano::Application do
51
51
 
52
52
  def command_line(*options)
53
53
  options.each { |opt| ARGV << opt }
54
- def subject.exit(*args)
54
+ subject.define_singleton_method(:exit) do |*_args|
55
55
  throw(:system_exit, :exit)
56
56
  end
57
57
  subject.run
58
58
  subject.options
59
59
  end
60
-
61
- def capture_io
62
- require 'stringio'
63
-
64
- orig_stdout, orig_stderr = $stdout, $stderr
65
- captured_stdout, captured_stderr = StringIO.new, StringIO.new
66
- $stdout, $stderr = captured_stdout, captured_stderr
67
-
68
- yield
69
-
70
- return captured_stdout.string, captured_stderr.string
71
- ensure
72
- $stdout = orig_stdout
73
- $stderr = orig_stderr
74
- end
75
-
76
60
  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 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  module Capistrano
4
4
  class Configuration
5
-
6
5
  describe Filter do
7
- let(:available) { [ Server.new('server1').add_roles([:web,:db]),
8
- Server.new('server2').add_role(:web),
9
- Server.new('server3').add_role(:redis),
10
- Server.new('server4').add_role(:db),
11
- Server.new('server5').add_role(:stageweb) ] }
6
+ let(:available) do
7
+ [
8
+ Server.new("server1").add_roles(%i(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
- describe '#new' do
16
+ describe "#new" do
14
17
  it "won't create an invalid type of filter" do
15
- expect {
16
- f = Filter.new(:zarg)
17
- }.to raise_error RuntimeError
18
+ expect do
19
+ Filter.new(:zarg)
20
+ end.to raise_error RuntimeError
18
21
  end
19
22
 
20
- it 'creates an empty host filter' do
21
- expect(Filter.new(:host).filter(available)).to be_empty
22
- end
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
- it 'creates a null host filter' do
25
- expect(Filter.new(:host, :all).filter(available)).to eq(available)
26
- end
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
- it 'creates an empty role filter' do
29
- expect(Filter.new(:role).filter(available)).to be_empty
30
- end
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
- it 'creates a null role filter' do
33
- expect(Filter.new(:role, :all).filter(available)).to eq(available)
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
- end
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
- describe 'host filter' do
39
- it 'works with a single server' do
40
- set = Filter.new(:host, 'server1').filter(available.first)
41
- expect(set.map(&:hostname)).to eq(%w{server1})
42
- end
43
- it 'returns all hosts matching a string' do
44
- set = Filter.new(:host, 'server1').filter(available)
45
- expect(set.map(&:hostname)).to eq(%w{server1})
46
- end
47
- it 'returns all hosts matching a comma-separated string' do
48
- set = Filter.new(:host, 'server1,server3').filter(available)
49
- expect(set.map(&:hostname)).to eq(%w{server1 server3})
50
- end
51
- it 'returns all hosts matching an array of strings' do
52
- set = Filter.new(:host, %w{server1 server3}).filter(available)
53
- expect(set.map(&:hostname)).to eq(%w{server1 server3})
54
- end
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 'role filter' do
66
- it 'returns all hosts' do
67
- set = Filter.new(:role, [:all]).filter(available)
68
- expect(set.size).to eq(available.size)
69
- expect(set.first.hostname).to eq('server1')
70
- end
71
- it 'returns hosts in a single string role' do
72
- set = Filter.new(:role, 'web').filter(available)
73
- expect(set.size).to eq(2)
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
- it 'returns only hosts for explicit roles' do
92
- set = Filter.new(:role, [:web]).filter(available)
93
- expect(set.size).to eq(2)
94
- expect(set.map(&:hostname)).to eq(%w{server1 server2})
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
- it 'returns hosts with regex role selection' do
97
- set = Filter.new(:role, /red/).filter(available)
98
- expect(set.map(&:hostname)).to eq(%w{server3})
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
- it 'returns hosts with regex role selection using a string' do
101
- set = Filter.new(:role, '/red|web/').filter(available)
102
- expect(set.map(&:hostname)).to eq(%w{server1 server2 server3 server5})
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
- it 'returns hosts with combination of string role and regex' do
105
- set = Filter.new(:role, 'db,/red/').filter(available)
106
- expect(set.map(&:hostname)).to eq(%w{server1 server3 server4})
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,71 @@
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("server10")]
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,server10" }
36
+ it_behaves_like "it filters hosts correctly", %w{server1 server10}
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 mixed splittable and unsplittable strings" do
45
+ let(:values) { %w{server1 server2,server3} }
46
+ it_behaves_like "it filters hosts correctly", %w{server1 server2 server3}
47
+ end
48
+
49
+ context "with a regexp" do
50
+ let(:values) { "server[13]$" }
51
+ it_behaves_like "it filters hosts correctly", %w{server1 server3}
52
+ end
53
+
54
+ context "with a regexp with line boundaries" do
55
+ let(:values) { "^server" }
56
+ it_behaves_like "it filters hosts correctly", %w{server1 server2 server3 server4 server10}
57
+ end
58
+
59
+ context "with a regexp with a comma" do
60
+ let(:values) { 'server\d{1,3}$' }
61
+ it_behaves_like "it filters hosts correctly", %w{server1 server2 server3 server4 server10}
62
+ end
63
+
64
+ context "without number" do
65
+ let(:values) { "server" }
66
+ it_behaves_like "it filters hosts correctly", %w{}
67
+ end
68
+ end
69
+ end
70
+ end
71
+ 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
@@ -0,0 +1,98 @@
1
+ require "spec_helper"
2
+ require "capistrano/plugin"
3
+ require "capistrano/scm/plugin"
4
+
5
+ module Capistrano
6
+ class Configuration
7
+ class ExamplePlugin < Capistrano::Plugin
8
+ def set_defaults
9
+ set_if_empty :example_variable, "foo"
10
+ end
11
+
12
+ def define_tasks
13
+ task :example
14
+ task :example_prerequisite
15
+ end
16
+
17
+ def register_hooks
18
+ before :example, :example_prerequisite
19
+ end
20
+ end
21
+
22
+ class ExampleSCMPlugin < Capistrano::SCM::Plugin
23
+ end
24
+
25
+ describe PluginInstaller do
26
+ include Capistrano::DSL
27
+
28
+ let(:installer) { PluginInstaller.new }
29
+ let(:options) { {} }
30
+ let(:plugin) { ExamplePlugin.new }
31
+
32
+ before do
33
+ installer.install(plugin, **options)
34
+ end
35
+
36
+ after do
37
+ Rake::Task.clear
38
+ Capistrano::Configuration.reset!
39
+ end
40
+
41
+ context "installing plugin" do
42
+ it "defines tasks" do
43
+ expect(Rake::Task[:example]).to_not be_nil
44
+ expect(Rake::Task[:example_prerequisite]).to_not be_nil
45
+ end
46
+
47
+ it "registers hooks" do
48
+ task = Rake::Task[:example]
49
+ expect(task.prerequisites).to eq([:example_prerequisite])
50
+ end
51
+
52
+ it "sets defaults when load:defaults is invoked", capture_io: true do
53
+ expect(fetch(:example_variable)).to be_nil
54
+ invoke "load:defaults"
55
+ expect(fetch(:example_variable)).to eq("foo")
56
+ end
57
+
58
+ it "doesn't say an SCM is installed" do
59
+ expect(installer.scm_installed?).to be_falsey
60
+ end
61
+ end
62
+
63
+ context "installing plugin class" do
64
+ let(:plugin) { ExamplePlugin }
65
+
66
+ it "defines tasks" do
67
+ expect(Rake::Task[:example]).to_not be_nil
68
+ expect(Rake::Task[:example_prerequisite]).to_not be_nil
69
+ end
70
+ end
71
+
72
+ context "installing plugin without hooks" do
73
+ let(:options) { { load_hooks: false } }
74
+
75
+ it "doesn't register hooks" do
76
+ task = Rake::Task[:example]
77
+ expect(task.prerequisites).to be_empty
78
+ end
79
+ end
80
+
81
+ context "installing plugin and loading immediately" do
82
+ let(:options) { { load_immediately: true } }
83
+
84
+ it "sets defaults immediately" do
85
+ expect(fetch(:example_variable)).to eq("foo")
86
+ end
87
+ end
88
+
89
+ context "installing an SCM plugin" do
90
+ let(:plugin) { ExampleSCMPlugin }
91
+
92
+ it "says an SCM is installed" do
93
+ expect(installer.scm_installed?).to be_truthy
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -1,60 +1,92 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  module Capistrano
4
4
  class Configuration
5
-
6
5
  describe Question do
7
-
8
- let(:question) { Question.new(key, default, options) }
9
- let(:question_without_echo) { Question.new(key, default, echo: false) }
6
+ let(:question) { Question.new(key, default, stdin: stdin) }
7
+ let(:question_without_echo) { Question.new(key, default, echo: false, stdin: stdin) }
8
+ let(:question_without_default) { Question.new(key, nil, stdin: stdin) }
9
+ let(:question_prompt) { Question.new(key, default, stdin: stdin, prompt: "Your favorite branch") }
10
+ let(:question_prompt_without_default) { Question.new(key, nil, stdin: stdin, prompt: "Your favorite branch") }
10
11
  let(:default) { :default }
11
12
  let(:key) { :branch }
12
- let(:options) { nil }
13
+ let(:stdin) { stub(tty?: true) }
13
14
 
14
- describe '.new' do
15
- it 'takes a key, default, options' do
15
+ describe ".new" do
16
+ it "takes a key, default, options" do
16
17
  question
17
18
  end
18
19
  end
19
20
 
20
- describe '#call' do
21
- context 'value is entered' do
22
- let(:branch) { 'branch' }
23
-
24
- before do
25
- $stdout.expects(:print).with('Please enter branch (default): ')
26
- end
21
+ describe "#call" do
22
+ context "value is entered" do
23
+ let(:branch) { "branch" }
27
24
 
28
- it 'returns the echoed value' do
29
- $stdin.expects(:gets).returns(branch)
30
- $stdin.expects(:noecho).never
25
+ it "returns the echoed value" do
26
+ $stdout.expects(:print).with("Please enter branch (default): ")
27
+ stdin.expects(:gets).returns(branch)
28
+ stdin.expects(:noecho).never
31
29
 
32
30
  expect(question.call).to eq(branch)
33
31
  end
34
32
 
35
- it 'returns the value but does not echo it' do
36
- $stdin.expects(:noecho).returns(branch)
33
+ it "returns the value but does not echo it" do
34
+ $stdout.expects(:print).with("Please enter branch (default): ")
35
+ stdin.expects(:noecho).returns(branch)
37
36
  $stdout.expects(:print).with("\n")
38
37
 
39
38
  expect(question_without_echo.call).to eq(branch)
40
39
  end
40
+
41
+ it "returns the value but has no default between parenthesis" do
42
+ $stdout.expects(:print).with("Please enter branch: ")
43
+ stdin.expects(:gets).returns(branch)
44
+ stdin.expects(:noecho).never
45
+
46
+ expect(question_without_default.call).to eq(branch)
47
+ end
48
+
49
+ it "uses prompt and returns the value" do
50
+ $stdout.expects(:print).with("Your favorite branch (default): ")
51
+ stdin.expects(:gets).returns(branch)
52
+ stdin.expects(:noecho).never
53
+
54
+ expect(question_prompt.call).to eq(branch)
55
+ end
56
+
57
+ it "uses prompt and returns the value but has no default between parenthesis" do
58
+ $stdout.expects(:print).with("Your favorite branch: ")
59
+ stdin.expects(:gets).returns(branch)
60
+ stdin.expects(:noecho).never
61
+
62
+ expect(question_prompt_without_default.call).to eq(branch)
63
+ end
41
64
  end
42
65
 
43
- context 'value is not entered' do
66
+ context "value is not entered" do
44
67
  let(:branch) { default }
45
68
 
46
69
  before do
47
- $stdout.expects(:print).with('Please enter branch (default): ')
48
- $stdin.expects(:gets).returns('')
70
+ $stdout.expects(:print).with("Please enter branch (default): ")
71
+ stdin.expects(:gets).returns("")
49
72
  end
50
73
 
51
-
52
- it 'returns the default as the value' do
74
+ it "returns the default as the value" do
53
75
  expect(question.call).to eq(branch)
54
76
  end
55
77
  end
78
+
79
+ context "tty unavailable", capture_io: true do
80
+ before do
81
+ stdin.expects(:gets).never
82
+ stdin.expects(:tty?).returns(false)
83
+ end
84
+
85
+ it "returns the default as the value" do
86
+ expect(question.call).to eq(default)
87
+ end
88
+ end
56
89
  end
57
90
  end
58
-
59
91
  end
60
92
  end