capistrano 3.11.0 → 3.19.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.
- checksums.yaml +4 -4
- data/.docker/Dockerfile +7 -0
- data/.docker/ssh_key_rsa +49 -0
- data/.docker/ssh_key_rsa.pub +1 -0
- data/.docker/ubuntu_setup.sh +23 -0
- data/.github/pull_request_template.md +0 -4
- data/.github/release-drafter.yml +25 -0
- data/.github/workflows/ci.yml +80 -0
- data/.github/workflows/release-drafter.yml +18 -0
- data/.rubocop.yml +4 -3
- data/CHANGELOG.md +1 -651
- data/DEVELOPMENT.md +5 -20
- data/Gemfile +40 -3
- data/LICENSE.txt +1 -1
- data/README.md +3 -3
- data/RELEASING.md +3 -3
- data/Rakefile +13 -5
- data/capistrano.gemspec +8 -7
- data/docker-compose.yml +8 -0
- data/features/deploy.feature +11 -1
- data/features/sshconnect.feature +1 -1
- data/features/step_definitions/assertions.rb +34 -24
- data/features/step_definitions/setup.rb +15 -16
- data/features/support/docker_gateway.rb +53 -0
- data/features/support/env.rb +0 -10
- data/features/support/remote_command_helpers.rb +3 -3
- data/features/support/remote_ssh_helpers.rb +33 -0
- data/lib/capistrano/configuration/question.rb +16 -4
- data/lib/capistrano/configuration/validated_variables.rb +1 -1
- data/lib/capistrano/doctor/variables_doctor.rb +2 -0
- data/lib/capistrano/dsl.rb +1 -1
- data/lib/capistrano/i18n.rb +2 -0
- data/lib/capistrano/scm/git.rb +15 -4
- data/lib/capistrano/scm/tasks/git.rake +19 -7
- data/lib/capistrano/tasks/deploy.rake +26 -3
- data/lib/capistrano/templates/deploy.rb.erb +2 -2
- data/lib/capistrano/templates/stage.rb.erb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/spec/integration/dsl_spec.rb +16 -14
- data/spec/lib/capistrano/application_spec.rb +16 -40
- data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +1 -1
- data/spec/lib/capistrano/configuration/question_spec.rb +31 -13
- data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +4 -2
- data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +1 -1
- data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +1 -1
- data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +1 -1
- data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +1 -1
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +6 -6
- data/spec/lib/capistrano/dsl_spec.rb +5 -5
- data/spec/lib/capistrano/plugin_spec.rb +2 -2
- data/spec/lib/capistrano/scm/git_spec.rb +37 -5
- data/spec/spec_helper.rb +13 -0
- data/spec/support/test_app.rb +23 -14
- metadata +25 -73
- data/.travis.yml +0 -27
- data/Dangerfile +0 -1
- data/features/support/vagrant_helpers.rb +0 -35
- data/spec/support/.gitignore +0 -1
- data/spec/support/Vagrantfile +0 -23
data/lib/capistrano/i18n.rb
CHANGED
@@ -12,6 +12,8 @@ en = {
|
|
12
12
|
written_file: "create %{file}",
|
13
13
|
question: "Please enter %{key}: ",
|
14
14
|
question_default: "Please enter %{key} (%{default_value}): ",
|
15
|
+
question_prompt: "%{key}: ",
|
16
|
+
question_prompt_default: "%{key} (%{default_value}): ",
|
15
17
|
keeping_releases: "Keeping %{keep_releases} of %{releases} deployed releases on %{host}",
|
16
18
|
skip_cleanup: "Skipping cleanup of invalid releases on %{host}; unexpected foldername found (should be timestamp)",
|
17
19
|
wont_delete_current_release: "Current release was marked for being removed but it's going to be skipped on %{host}",
|
data/lib/capistrano/scm/git.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "capistrano/scm/plugin"
|
2
2
|
require "cgi"
|
3
|
+
require "securerandom"
|
3
4
|
require "shellwords"
|
4
5
|
require "uri"
|
5
6
|
|
@@ -7,10 +8,9 @@ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
|
7
8
|
def set_defaults
|
8
9
|
set_if_empty :git_shallow_clone, false
|
9
10
|
set_if_empty :git_wrapper_path, lambda {
|
10
|
-
#
|
11
|
-
#
|
12
|
-
|
13
|
-
"#{fetch(:tmp_dir)}/git-ssh-#{suffix}.sh"
|
11
|
+
# Use a unique name that won't collide with other deployments, and
|
12
|
+
# that cannot be guessed by other processes that have access to /tmp.
|
13
|
+
"#{fetch(:tmp_dir)}/git-ssh-#{SecureRandom.hex(10)}.sh"
|
14
14
|
}
|
15
15
|
set_if_empty :git_environmental_variables, lambda {
|
16
16
|
{
|
@@ -18,12 +18,15 @@ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
|
18
18
|
git_ssh: fetch(:git_wrapper_path)
|
19
19
|
}
|
20
20
|
}
|
21
|
+
set_if_empty :git_max_concurrent_connections, 10
|
22
|
+
set_if_empty :git_wait_interval, 0
|
21
23
|
end
|
22
24
|
|
23
25
|
def register_hooks
|
24
26
|
after "deploy:new_release_path", "git:create_release"
|
25
27
|
before "deploy:check", "git:check"
|
26
28
|
before "deploy:set_current_revision", "git:set_current_revision"
|
29
|
+
before "deploy:set_current_revision_time", "git:set_current_revision_time"
|
27
30
|
end
|
28
31
|
|
29
32
|
def define_tasks
|
@@ -58,6 +61,10 @@ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
|
58
61
|
end
|
59
62
|
end
|
60
63
|
|
64
|
+
def verify_commit
|
65
|
+
git :"verify-commit", fetch_revision
|
66
|
+
end
|
67
|
+
|
61
68
|
def archive_to_release_path
|
62
69
|
if (tree = fetch(:repo_tree))
|
63
70
|
tree = tree.slice %r#^/?(.*?)/?$#, 1
|
@@ -72,6 +79,10 @@ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
|
72
79
|
backend.capture(:git, "rev-list --max-count=1 #{fetch(:branch)}")
|
73
80
|
end
|
74
81
|
|
82
|
+
def fetch_revision_time
|
83
|
+
backend.capture(:git, "--no-pager log -1 --pretty=format:\"%ct\" #{fetch(:branch)}")
|
84
|
+
end
|
85
|
+
|
75
86
|
def git(*args)
|
76
87
|
args.unshift :git
|
77
88
|
backend.execute(*args)
|
@@ -4,9 +4,9 @@ git_plugin = self
|
|
4
4
|
namespace :git do
|
5
5
|
desc "Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt"
|
6
6
|
task :wrapper do
|
7
|
-
on release_roles
|
7
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
8
8
|
execute :mkdir, "-p", File.dirname(fetch(:git_wrapper_path)).shellescape
|
9
|
-
upload! StringIO.new("#!/bin/sh -e\nexec /usr/bin/ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no \"$@\"\n"), fetch(:git_wrapper_path)
|
9
|
+
upload! StringIO.new("#!/bin/sh -e\nexec /usr/bin/env ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no \"$@\"\n"), fetch(:git_wrapper_path)
|
10
10
|
execute :chmod, "700", fetch(:git_wrapper_path).shellescape
|
11
11
|
end
|
12
12
|
end
|
@@ -14,7 +14,7 @@ namespace :git do
|
|
14
14
|
desc "Check that the repository is reachable"
|
15
15
|
task check: :'git:wrapper' do
|
16
16
|
fetch(:branch)
|
17
|
-
on release_roles
|
17
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
18
18
|
with fetch(:git_environmental_variables) do
|
19
19
|
git_plugin.check_repo_is_reachable
|
20
20
|
end
|
@@ -23,7 +23,7 @@ namespace :git do
|
|
23
23
|
|
24
24
|
desc "Clone the repo to the cache"
|
25
25
|
task clone: :'git:wrapper' do
|
26
|
-
on release_roles
|
26
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
27
27
|
if git_plugin.repo_mirror_exists?
|
28
28
|
info t(:mirror_exists, at: repo_path)
|
29
29
|
else
|
@@ -38,10 +38,11 @@ namespace :git do
|
|
38
38
|
|
39
39
|
desc "Update the repo mirror to reflect the origin state"
|
40
40
|
task update: :'git:clone' do
|
41
|
-
on release_roles
|
41
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
42
42
|
within repo_path do
|
43
43
|
with fetch(:git_environmental_variables) do
|
44
44
|
git_plugin.update_mirror
|
45
|
+
git_plugin.verify_commit if fetch(:git_verify_commit)
|
45
46
|
end
|
46
47
|
end
|
47
48
|
end
|
@@ -49,7 +50,7 @@ namespace :git do
|
|
49
50
|
|
50
51
|
desc "Copy repo to releases"
|
51
52
|
task create_release: :'git:update' do
|
52
|
-
on release_roles
|
53
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
53
54
|
with fetch(:git_environmental_variables) do
|
54
55
|
within repo_path do
|
55
56
|
execute :mkdir, "-p", release_path
|
@@ -61,7 +62,7 @@ namespace :git do
|
|
61
62
|
|
62
63
|
desc "Determine the revision that will be deployed"
|
63
64
|
task :set_current_revision do
|
64
|
-
on release_roles
|
65
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
65
66
|
within repo_path do
|
66
67
|
with fetch(:git_environmental_variables) do
|
67
68
|
set :current_revision, git_plugin.fetch_revision
|
@@ -69,4 +70,15 @@ namespace :git do
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
end
|
73
|
+
|
74
|
+
desc "Determine the unix timestamp that the revision that will be deployed was created"
|
75
|
+
task :set_current_revision_time do
|
76
|
+
on release_roles(:all), in: :groups, limit: fetch(:git_max_concurrent_connections), wait: fetch(:git_wait_interval) do
|
77
|
+
within repo_path do
|
78
|
+
with fetch(:git_environmental_variables) do
|
79
|
+
set :current_revision_time, git_plugin.fetch_revision_time
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
72
84
|
end
|
@@ -3,6 +3,7 @@ namespace :deploy do
|
|
3
3
|
invoke "deploy:print_config_variables" if fetch(:print_config_variables, false)
|
4
4
|
invoke "deploy:check"
|
5
5
|
invoke "deploy:set_previous_revision"
|
6
|
+
invoke "deploy:set_previous_revision_time"
|
6
7
|
end
|
7
8
|
|
8
9
|
task :print_config_variables do
|
@@ -27,6 +28,7 @@ namespace :deploy do
|
|
27
28
|
|
28
29
|
task updating: :new_release_path do
|
29
30
|
invoke "deploy:set_current_revision"
|
31
|
+
invoke "deploy:set_current_revision_time"
|
30
32
|
invoke "deploy:symlink:shared"
|
31
33
|
end
|
32
34
|
|
@@ -168,8 +170,9 @@ namespace :deploy do
|
|
168
170
|
debug t(:no_current_release, host: host.to_s)
|
169
171
|
end
|
170
172
|
if directories.any?
|
171
|
-
|
172
|
-
|
173
|
+
directories.each_slice(100) do |directories_batch|
|
174
|
+
execute :rm, "-rf", *directories_batch
|
175
|
+
end
|
173
176
|
else
|
174
177
|
info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
|
175
178
|
end
|
@@ -235,7 +238,7 @@ namespace :deploy do
|
|
235
238
|
end
|
236
239
|
|
237
240
|
desc "Place a REVISION file with the current revision SHA in the current release path"
|
238
|
-
task :set_current_revision
|
241
|
+
task :set_current_revision do
|
239
242
|
on release_roles(:all) do
|
240
243
|
within release_path do
|
241
244
|
execute :echo, "\"#{fetch(:current_revision)}\" > REVISION"
|
@@ -252,6 +255,26 @@ namespace :deploy do
|
|
252
255
|
end
|
253
256
|
end
|
254
257
|
|
258
|
+
desc "Place a REVISION_TIME file with the current revision commit time in the current release path"
|
259
|
+
task :set_current_revision_time do
|
260
|
+
on release_roles(:all) do
|
261
|
+
within release_path do
|
262
|
+
if fetch(:current_revision_time)
|
263
|
+
execute :echo, "\"#{fetch(:current_revision_time)}\" > REVISION_TIME"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
task :set_previous_revision_time do
|
270
|
+
on release_roles(:all) do
|
271
|
+
target = release_path.join("REVISION_TIME")
|
272
|
+
if test "[ -f #{target} ]"
|
273
|
+
set(:previous_revision_time, capture(:cat, target, "2>/dev/null"))
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
255
278
|
task :restart
|
256
279
|
task :failed
|
257
280
|
end
|
@@ -21,10 +21,10 @@ set :repo_url, "git@example.com:me/my_repo.git"
|
|
21
21
|
# set :pty, true
|
22
22
|
|
23
23
|
# Default value for :linked_files is []
|
24
|
-
# append :linked_files, "config/database.yml"
|
24
|
+
# append :linked_files, "config/database.yml", 'config/master.key'
|
25
25
|
|
26
26
|
# Default value for linked_dirs is []
|
27
|
-
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
|
27
|
+
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system", "vendor", "storage"
|
28
28
|
|
29
29
|
# Default value for default_env is {}
|
30
30
|
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
|
data/lib/capistrano/version.rb
CHANGED
@@ -247,7 +247,7 @@ describe Capistrano::DSL do
|
|
247
247
|
end
|
248
248
|
end
|
249
249
|
|
250
|
-
context "when the attribute `primary` is
|
250
|
+
context "when the attribute `primary` is explicitly set" do
|
251
251
|
subject { dsl.primary(:app) }
|
252
252
|
it "returns the servers" do
|
253
253
|
expect(subject.hostname).to eq "example4.com"
|
@@ -356,14 +356,16 @@ describe Capistrano::DSL do
|
|
356
356
|
end
|
357
357
|
|
358
358
|
describe "asking for a variable" do
|
359
|
+
let(:stdin) { stub(tty?: true) }
|
360
|
+
|
359
361
|
before do
|
360
|
-
dsl.ask(:scm, :svn)
|
362
|
+
dsl.ask(:scm, :svn, stdin: stdin)
|
361
363
|
$stdout.stubs(:print)
|
362
364
|
end
|
363
365
|
|
364
366
|
context "variable is provided" do
|
365
367
|
before do
|
366
|
-
|
368
|
+
stdin.expects(:gets).returns("git")
|
367
369
|
end
|
368
370
|
|
369
371
|
it "sets the input as the variable" do
|
@@ -373,7 +375,7 @@ describe Capistrano::DSL do
|
|
373
375
|
|
374
376
|
context "variable is not provided" do
|
375
377
|
before do
|
376
|
-
|
378
|
+
stdin.expects(:gets).returns("")
|
377
379
|
end
|
378
380
|
|
379
381
|
it "sets the variable as the default" do
|
@@ -590,8 +592,8 @@ describe Capistrano::DSL do
|
|
590
592
|
|
591
593
|
it "yields the properties for a single role" do
|
592
594
|
recipient = mock("recipient")
|
593
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
594
|
-
recipient.expects(:doit).with("example2.com", :redis, port: 6379, type: :master)
|
595
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
596
|
+
recipient.expects(:doit).with("example2.com", :redis, { port: 6379, type: :master })
|
595
597
|
dsl.role_properties(:redis) do |host, role, props|
|
596
598
|
recipient.doit(host, role, props)
|
597
599
|
end
|
@@ -599,8 +601,8 @@ describe Capistrano::DSL do
|
|
599
601
|
|
600
602
|
it "yields the properties for multiple roles" do
|
601
603
|
recipient = mock("recipient")
|
602
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
603
|
-
recipient.expects(:doit).with("example2.com", :redis, port: 6379, type: :master)
|
604
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
605
|
+
recipient.expects(:doit).with("example2.com", :redis, { port: 6379, type: :master })
|
604
606
|
recipient.expects(:doit).with("example3.com", :app, nil)
|
605
607
|
dsl.role_properties(:redis, :app) do |host, role, props|
|
606
608
|
recipient.doit(host, role, props)
|
@@ -609,10 +611,10 @@ describe Capistrano::DSL do
|
|
609
611
|
|
610
612
|
it "yields the merged properties for multiple roles" do
|
611
613
|
recipient = mock("recipient")
|
612
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
613
|
-
recipient.expects(:doit).with("example2.com", :redis, port: 6379, type: :master)
|
614
|
-
recipient.expects(:doit).with("example1.com", :web, port: 80)
|
615
|
-
recipient.expects(:doit).with("example2.com", :web, port: 81)
|
614
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
615
|
+
recipient.expects(:doit).with("example2.com", :redis, { port: 6379, type: :master })
|
616
|
+
recipient.expects(:doit).with("example1.com", :web, { port: 80 })
|
617
|
+
recipient.expects(:doit).with("example2.com", :web, { port: 81 })
|
616
618
|
dsl.role_properties(:redis, :web) do |host, role, props|
|
617
619
|
recipient.doit(host, role, props)
|
618
620
|
end
|
@@ -620,8 +622,8 @@ describe Capistrano::DSL do
|
|
620
622
|
|
621
623
|
it "honours a property filter before yielding" do
|
622
624
|
recipient = mock("recipient")
|
623
|
-
recipient.expects(:doit).with("example1.com", :redis, port: 6379, type: :slave)
|
624
|
-
recipient.expects(:doit).with("example1.com", :web, port: 80)
|
625
|
+
recipient.expects(:doit).with("example1.com", :redis, { port: 6379, type: :slave })
|
626
|
+
recipient.expects(:doit).with("example1.com", :web, { port: 80 })
|
625
627
|
dsl.role_properties(:redis, :web, select: :active) do |host, role, props|
|
626
628
|
recipient.doit(host, role, props)
|
627
629
|
end
|
@@ -5,46 +5,40 @@ describe Capistrano::Application do
|
|
5
5
|
|
6
6
|
it "provides a --format option which enables the choice of output formatting"
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
out
|
13
|
-
end
|
14
|
-
|
15
|
-
it "displays documentation URL as help banner" do
|
16
|
-
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/)
|
17
11
|
end
|
18
12
|
|
19
13
|
%w(quiet silent verbose).each do |switch|
|
20
|
-
it "doesn't include --#{switch} in help" do
|
21
|
-
|
14
|
+
it "doesn't include --#{switch} in help", capture_io: true do
|
15
|
+
flags "--help", "-h"
|
16
|
+
expect($stdout.string).not_to match(/--#{switch}/)
|
22
17
|
end
|
23
18
|
end
|
24
19
|
|
25
|
-
it "overrides the rake method, but still prints the rake version" do
|
26
|
-
|
27
|
-
|
28
|
-
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
|
29
23
|
expect(out).to match(/\bCapistrano Version\b/)
|
30
24
|
expect(out).to match(/\b#{Capistrano::VERSION}\b/)
|
31
25
|
expect(out).to match(/\bRake Version\b/)
|
32
26
|
expect(out).to match(/\b#{Rake::VERSION}\b/)
|
33
27
|
end
|
34
28
|
|
35
|
-
it "overrides the rake method, and sets the sshkit_backend to SSHKit::Backend::Printer" do
|
36
|
-
|
37
|
-
flags "--dry-run", "-n"
|
38
|
-
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"
|
39
31
|
sshkit_backend = Capistrano::Configuration.fetch(:sshkit_backend)
|
40
32
|
expect(sshkit_backend).to eq(SSHKit::Backend::Printer)
|
41
33
|
end
|
42
34
|
|
43
|
-
it "enables printing all config variables on command line parameter" do
|
44
|
-
|
35
|
+
it "enables printing all config variables on command line parameter", capture_io: true do
|
36
|
+
begin
|
45
37
|
flags "--print-config-variables", "-p"
|
38
|
+
expect(Capistrano::Configuration.fetch(:print_config_variables)).to be true
|
39
|
+
ensure
|
40
|
+
Capistrano::Configuration.reset!
|
46
41
|
end
|
47
|
-
expect(Capistrano::Configuration.fetch(:print_config_variables)).to be true
|
48
42
|
end
|
49
43
|
|
50
44
|
def flags(*sets)
|
@@ -63,22 +57,4 @@ describe Capistrano::Application do
|
|
63
57
|
subject.run
|
64
58
|
subject.options
|
65
59
|
end
|
66
|
-
|
67
|
-
def capture_io
|
68
|
-
require "stringio"
|
69
|
-
|
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
|
76
|
-
|
77
|
-
yield
|
78
|
-
|
79
|
-
return captured_stdout.string, captured_stderr.string
|
80
|
-
ensure
|
81
|
-
$stdout = orig_stdout
|
82
|
-
$stderr = orig_stderr
|
83
|
-
end
|
84
60
|
end
|
@@ -49,7 +49,7 @@ module Capistrano
|
|
49
49
|
expect(task.prerequisites).to eq([:example_prerequisite])
|
50
50
|
end
|
51
51
|
|
52
|
-
it "sets defaults when load:defaults is invoked" do
|
52
|
+
it "sets defaults when load:defaults is invoked", capture_io: true do
|
53
53
|
expect(fetch(:example_variable)).to be_nil
|
54
54
|
invoke "load:defaults"
|
55
55
|
expect(fetch(:example_variable)).to eq("foo")
|
@@ -3,12 +3,14 @@ require "spec_helper"
|
|
3
3
|
module Capistrano
|
4
4
|
class Configuration
|
5
5
|
describe Question do
|
6
|
-
let(:question) { Question.new(key, default,
|
7
|
-
let(:question_without_echo) { Question.new(key, default, echo: false) }
|
8
|
-
let(:question_without_default) { Question.new(key, nil) }
|
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") }
|
9
11
|
let(:default) { :default }
|
10
12
|
let(:key) { :branch }
|
11
|
-
let(:
|
13
|
+
let(:stdin) { stub(tty?: true) }
|
12
14
|
|
13
15
|
describe ".new" do
|
14
16
|
it "takes a key, default, options" do
|
@@ -22,15 +24,15 @@ module Capistrano
|
|
22
24
|
|
23
25
|
it "returns the echoed value" do
|
24
26
|
$stdout.expects(:print).with("Please enter branch (default): ")
|
25
|
-
|
26
|
-
|
27
|
+
stdin.expects(:gets).returns(branch)
|
28
|
+
stdin.expects(:noecho).never
|
27
29
|
|
28
30
|
expect(question.call).to eq(branch)
|
29
31
|
end
|
30
32
|
|
31
33
|
it "returns the value but does not echo it" do
|
32
34
|
$stdout.expects(:print).with("Please enter branch (default): ")
|
33
|
-
|
35
|
+
stdin.expects(:noecho).returns(branch)
|
34
36
|
$stdout.expects(:print).with("\n")
|
35
37
|
|
36
38
|
expect(question_without_echo.call).to eq(branch)
|
@@ -38,11 +40,27 @@ module Capistrano
|
|
38
40
|
|
39
41
|
it "returns the value but has no default between parenthesis" do
|
40
42
|
$stdout.expects(:print).with("Please enter branch: ")
|
41
|
-
|
42
|
-
|
43
|
+
stdin.expects(:gets).returns(branch)
|
44
|
+
stdin.expects(:noecho).never
|
43
45
|
|
44
46
|
expect(question_without_default.call).to eq(branch)
|
45
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
|
46
64
|
end
|
47
65
|
|
48
66
|
context "value is not entered" do
|
@@ -50,7 +68,7 @@ module Capistrano
|
|
50
68
|
|
51
69
|
before do
|
52
70
|
$stdout.expects(:print).with("Please enter branch (default): ")
|
53
|
-
|
71
|
+
stdin.expects(:gets).returns("")
|
54
72
|
end
|
55
73
|
|
56
74
|
it "returns the default as the value" do
|
@@ -58,10 +76,10 @@ module Capistrano
|
|
58
76
|
end
|
59
77
|
end
|
60
78
|
|
61
|
-
context "tty unavailable" do
|
79
|
+
context "tty unavailable", capture_io: true do
|
62
80
|
before do
|
63
|
-
|
64
|
-
|
81
|
+
stdin.expects(:gets).never
|
82
|
+
stdin.expects(:tty?).returns(false)
|
65
83
|
end
|
66
84
|
|
67
85
|
it "returns the default as the value" do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "spec_helper"
|
2
|
+
require "capistrano/scm"
|
2
3
|
|
3
4
|
module Capistrano
|
4
5
|
class Configuration
|
@@ -11,6 +12,7 @@ module Capistrano
|
|
11
12
|
Rake::Task.define_task("deploy:check")
|
12
13
|
Rake::Task.define_task("deploy:new_release_path")
|
13
14
|
Rake::Task.define_task("deploy:set_current_revision")
|
15
|
+
Rake::Task.define_task("deploy:set_current_revision_time")
|
14
16
|
set :scm, SCMResolver::DEFAULT_GIT
|
15
17
|
end
|
16
18
|
|
@@ -24,12 +26,12 @@ module Capistrano
|
|
24
26
|
expect { resolver.resolve }.to output(/will not load the git scm/i).to_stderr
|
25
27
|
end
|
26
28
|
|
27
|
-
it "activates the git scm" do
|
29
|
+
it "activates the git scm", capture_io: true do
|
28
30
|
resolver.resolve
|
29
31
|
expect(Rake::Task["git:wrapper"]).not_to be_nil
|
30
32
|
end
|
31
33
|
|
32
|
-
it "sets :scm to :git" do
|
34
|
+
it "sets :scm to :git", capture_io: true do
|
33
35
|
resolver.resolve
|
34
36
|
expect(fetch(:scm)).to eq(:git)
|
35
37
|
end
|
@@ -29,7 +29,7 @@ module Capistrano
|
|
29
29
|
Rake::Task.clear
|
30
30
|
end
|
31
31
|
|
32
|
-
it "has an doctor:environment task that calls EnvironmentDoctor" do
|
32
|
+
it "has an doctor:environment task that calls EnvironmentDoctor", capture_io: true do
|
33
33
|
EnvironmentDoctor.any_instance.expects(:call)
|
34
34
|
Rake::Task["doctor:environment"].invoke
|
35
35
|
end
|
@@ -53,7 +53,7 @@ module Capistrano
|
|
53
53
|
Rake::Task.clear
|
54
54
|
end
|
55
55
|
|
56
|
-
it "has an doctor:gems task that calls GemsDoctor" do
|
56
|
+
it "has an doctor:gems task that calls GemsDoctor", capture_io: true do
|
57
57
|
GemsDoctor.any_instance.expects(:call)
|
58
58
|
Rake::Task["doctor:gems"].invoke
|
59
59
|
end
|
@@ -71,7 +71,7 @@ module Capistrano
|
|
71
71
|
Rake::Task.clear
|
72
72
|
end
|
73
73
|
|
74
|
-
it "has an doctor:servers task that calls ServersDoctor" do
|
74
|
+
it "has an doctor:servers task that calls ServersDoctor", capture_io: true do
|
75
75
|
ServersDoctor.any_instance.expects(:call)
|
76
76
|
Rake::Task["doctor:servers"].invoke
|
77
77
|
end
|
@@ -74,7 +74,7 @@ module Capistrano
|
|
74
74
|
Rake::Task.clear
|
75
75
|
end
|
76
76
|
|
77
|
-
it "has an doctor:variables task that calls VariablesDoctor" do
|
77
|
+
it "has an doctor:variables task that calls VariablesDoctor", capture_io: true do
|
78
78
|
VariablesDoctor.any_instance.expects(:call)
|
79
79
|
Rake::Task["doctor:variables"].invoke
|
80
80
|
end
|
@@ -35,7 +35,7 @@ module Capistrano
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
it "invokes in proper order if define after than before" do
|
38
|
+
it "invokes in proper order if define after than before", capture_io: true do
|
39
39
|
task_enhancements.after("task", "after_task")
|
40
40
|
task_enhancements.before("task", "before_task")
|
41
41
|
|
@@ -44,7 +44,7 @@ module Capistrano
|
|
44
44
|
expect(order).to eq(%w(before_task task after_task))
|
45
45
|
end
|
46
46
|
|
47
|
-
it "invokes in proper order if define before than after" do
|
47
|
+
it "invokes in proper order if define before than after", capture_io: true do
|
48
48
|
task_enhancements.before("task", "before_task")
|
49
49
|
task_enhancements.after("task", "after_task")
|
50
50
|
|
@@ -53,7 +53,7 @@ module Capistrano
|
|
53
53
|
expect(order).to eq(%w(before_task task after_task))
|
54
54
|
end
|
55
55
|
|
56
|
-
it "invokes in proper order when referring to as-yet undefined tasks" do
|
56
|
+
it "invokes in proper order when referring to as-yet undefined tasks", capture_io: true do
|
57
57
|
task_enhancements.after("task", "not_loaded_task")
|
58
58
|
|
59
59
|
Rake::Task.define_task("not_loaded_task") do
|
@@ -65,7 +65,7 @@ module Capistrano
|
|
65
65
|
expect(order).to eq(%w(task not_loaded_task))
|
66
66
|
end
|
67
67
|
|
68
|
-
it "invokes in proper order and with arguments and block" do
|
68
|
+
it "invokes in proper order and with arguments and block", capture_io: true do
|
69
69
|
task_enhancements.after("task", "after_task_custom", :order) do |_t, _args|
|
70
70
|
order.push "after_task"
|
71
71
|
end
|
@@ -79,7 +79,7 @@ module Capistrano
|
|
79
79
|
expect(order).to eq(%w(before_task task after_task))
|
80
80
|
end
|
81
81
|
|
82
|
-
it "invokes using the correct namespace when defined within a namespace" do
|
82
|
+
it "invokes using the correct namespace when defined within a namespace", capture_io: true do
|
83
83
|
Rake.application.in_namespace("namespace") do
|
84
84
|
Rake::Task.define_task("task") do |t|
|
85
85
|
order.push(t.name)
|
@@ -99,7 +99,7 @@ module Capistrano
|
|
99
99
|
)
|
100
100
|
end
|
101
101
|
|
102
|
-
it "raises a sensible error if the task isn't found" do
|
102
|
+
it "raises a sensible error if the task isn't found", capture_io: true do
|
103
103
|
task_enhancements.after("task", "non_existent_task")
|
104
104
|
expect { Rake::Task["task"].invoke order }.to raise_error(ArgumentError, 'Task "non_existent_task" not found')
|
105
105
|
end
|