capistrano 3.11.0 → 3.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/pull_request_template.md +0 -4
- data/.github/release-drafter.yml +17 -0
- data/.github/workflows/push.yml +12 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +10 -7
- data/CHANGELOG.md +1 -651
- data/Dangerfile +1 -1
- data/Gemfile +33 -1
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/RELEASING.md +3 -3
- data/Rakefile +5 -0
- data/capistrano.gemspec +8 -3
- data/features/deploy.feature +6 -0
- data/features/step_definitions/assertions.rb +1 -1
- data/features/step_definitions/setup.rb +6 -4
- data/features/support/vagrant_helpers.rb +6 -0
- data/lib/capistrano/configuration/question.rb +16 -4
- data/lib/capistrano/dsl.rb +1 -1
- data/lib/capistrano/i18n.rb +2 -0
- data/lib/capistrano/scm/git.rb +10 -4
- data/lib/capistrano/scm/tasks/git.rake +8 -7
- data/lib/capistrano/tasks/deploy.rake +3 -2
- data/lib/capistrano/templates/stage.rb.erb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/spec/integration/dsl_spec.rb +5 -3
- 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 +3 -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 +27 -5
- data/spec/spec_helper.rb +13 -0
- data/spec/support/test_app.rb +8 -3
- metadata +15 -23
data/Gemfile
CHANGED
@@ -4,7 +4,39 @@ source "https://rubygems.org"
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
group :cucumber do
|
7
|
-
|
7
|
+
# Latest versions of cucumber don't support Ruby < 2.1
|
8
|
+
# rubocop:disable Bundler/DuplicatedGem
|
9
|
+
if Gem::Requirement.new("< 2.1").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
10
|
+
gem "cucumber", "< 3.0.1"
|
11
|
+
else
|
12
|
+
gem "cucumber"
|
13
|
+
end
|
14
|
+
# rubocop:enable Bundler/DuplicatedGem
|
8
15
|
gem "rspec"
|
9
16
|
gem "rspec-core", "~> 3.4.4"
|
10
17
|
end
|
18
|
+
|
19
|
+
# Latest versions of net-ssh don't support Ruby < 2.2.6
|
20
|
+
if Gem::Requirement.new("< 2.2.6").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
21
|
+
gem "net-ssh", "< 5.0.0"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Latest versions of public_suffix don't support Ruby < 2.1
|
25
|
+
if Gem::Requirement.new("< 2.1").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
26
|
+
gem "public_suffix", "< 3.0.0"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Latest versions of i18n don't support Ruby < 2.4
|
30
|
+
if Gem::Requirement.new("< 2.4").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
31
|
+
gem "i18n", "< 1.3.0"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Latest versions of rake don't support Ruby < 2.2
|
35
|
+
if Gem::Requirement.new("< 2.2").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
36
|
+
gem "rake", "< 13.0.0"
|
37
|
+
end
|
38
|
+
|
39
|
+
# We only run danger once on a new-ish ruby; no need to install it otherwise
|
40
|
+
if Gem::Requirement.new("> 2.4").satisfied_by?(Gem::Version.new(RUBY_VERSION))
|
41
|
+
gem "danger"
|
42
|
+
end
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2012-
|
3
|
+
Copyright (c) 2012-2020 Tom Clements, Lee Hambley
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -107,7 +107,7 @@ Add Capistrano to your project's Gemfile using `require: false`:
|
|
107
107
|
|
108
108
|
``` ruby
|
109
109
|
group :development do
|
110
|
-
gem "capistrano", "~> 3.
|
110
|
+
gem "capistrano", "~> 3.16", require: false
|
111
111
|
end
|
112
112
|
```
|
113
113
|
|
@@ -200,7 +200,7 @@ Contributions to Capistrano, in the form of code, documentation or idea, are gla
|
|
200
200
|
|
201
201
|
MIT License (MIT)
|
202
202
|
|
203
|
-
Copyright (c) 2012-
|
203
|
+
Copyright (c) 2012-2020 Tom Clements, Lee Hambley
|
204
204
|
|
205
205
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
206
206
|
of this software and associated documentation files (the "Software"), to deal
|
data/RELEASING.md
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
2. **Ensure all tests are passing by running `rake spec` and `rake features`.**
|
12
12
|
3. Determine which would be the correct next version number according to [semver](http://semver.org/).
|
13
13
|
4. Update the version in `./lib/capistrano/version.rb`.
|
14
|
-
|
15
|
-
|
16
|
-
6. Commit the changelog and version in a single commit, the message should be "Preparing vX.Y.Z"
|
14
|
+
5. Update the version in the `./README.md` Gemfile example (`gem "capistrano", "~> X.Y"`).
|
15
|
+
6. Commit the `version.rb` and `README.md` changes in a single commit, the message should be "Release vX.Y.Z"
|
17
16
|
7. Run `rake release`; this will tag, push to GitHub, and publish to rubygems.org.
|
17
|
+
8. Update the draft release on the [GitHub releases page](https://github.com/capistrano/capistrano/releases) to point to the new tag and publish the release
|
data/Rakefile
CHANGED
data/capistrano.gemspec
CHANGED
@@ -11,8 +11,14 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.email = ["seenmyfate@gmail.com", "lee.hambley@gmail.com"]
|
12
12
|
gem.description = "Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH."
|
13
13
|
gem.summary = "Capistrano - Welcome to easy deployment with Ruby over SSH"
|
14
|
-
gem.homepage = "
|
15
|
-
|
14
|
+
gem.homepage = "https://capistranorb.com/"
|
15
|
+
gem.metadata = {
|
16
|
+
"bug_tracker_uri" => "https://github.com/capistrano/capistrano/issues",
|
17
|
+
"changelog_uri" => "https://github.com/capistrano/capistrano/releases",
|
18
|
+
"source_code_uri" => "https://github.com/capistrano/capistrano",
|
19
|
+
"homepage_uri" => "https://capistranorb.com/",
|
20
|
+
"documentation_uri" => "https://capistranorb.com/"
|
21
|
+
}
|
16
22
|
gem.files = `git ls-files -z`.split("\x0").reject { |f| f =~ /^docs/ }
|
17
23
|
gem.executables = %w(cap capify)
|
18
24
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
@@ -26,7 +32,6 @@ Gem::Specification.new do |gem|
|
|
26
32
|
gem.add_dependency "rake", ">= 10.0.0"
|
27
33
|
gem.add_dependency "sshkit", ">= 1.9.0"
|
28
34
|
|
29
|
-
gem.add_development_dependency "danger"
|
30
35
|
gem.add_development_dependency "mocha"
|
31
36
|
gem.add_development_dependency "rspec"
|
32
37
|
gem.add_development_dependency "rubocop", "0.48.1"
|
data/features/deploy.feature
CHANGED
@@ -70,6 +70,12 @@ Feature: Deploy
|
|
70
70
|
Then 3 valid releases are kept
|
71
71
|
And the current directory will be a symlink to the release
|
72
72
|
|
73
|
+
Scenario: Cleanup when there are more releases than arguments can handle
|
74
|
+
Given config stage file has line "set :keep_releases, 3"
|
75
|
+
And 5000 valid existing releases
|
76
|
+
When I run cap "deploy:cleanup"
|
77
|
+
Then 3 valid releases are kept
|
78
|
+
|
73
79
|
Scenario: Rolling Back
|
74
80
|
Given I make 2 deployments
|
75
81
|
When I run cap "deploy:rollback"
|
@@ -5,7 +5,7 @@ Then(/^references in the remote repo are listed$/) do
|
|
5
5
|
end
|
6
6
|
|
7
7
|
Then(/^git wrapper permissions are 0700$/) do
|
8
|
-
permissions_test = %Q([ $(stat -c "%a" #{TestApp.
|
8
|
+
permissions_test = %Q([ $(stat -c "%a" #{TestApp.git_wrapper_path_glob}) == "700" ])
|
9
9
|
_stdout, _stderr, status = vagrant_cli_command("ssh -c #{permissions_test.shellescape}")
|
10
10
|
|
11
11
|
expect(status).to be_success
|
@@ -80,10 +80,12 @@ end
|
|
80
80
|
|
81
81
|
Given(/^(\d+) valid existing releases$/) do |num|
|
82
82
|
a_day = 86_400 # in seconds
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
(1...num).each_slice(100) do |num_batch|
|
84
|
+
dirs = num_batch.map do |i|
|
85
|
+
offset = -(a_day * i)
|
86
|
+
TestApp.release_path(TestApp.timestamp(offset))
|
87
|
+
end
|
88
|
+
run_vagrant_command("mkdir -p #{dirs.join(' ')}")
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
@@ -30,6 +30,12 @@ module VagrantHelpers
|
|
30
30
|
return [stdout, stderr] if status.success?
|
31
31
|
raise VagrantSSHCommandError, status
|
32
32
|
end
|
33
|
+
|
34
|
+
def puts(message)
|
35
|
+
# Attach log messages to the current cucumber feature (`log`),
|
36
|
+
# or simply puts to the console (`super`) if we are outside of cucumber.
|
37
|
+
respond_to?(:log) ? log(message) : super(message)
|
38
|
+
end
|
33
39
|
end
|
34
40
|
|
35
41
|
World(VagrantHelpers)
|
@@ -36,12 +36,12 @@ module Capistrano
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def gets
|
39
|
-
return unless
|
39
|
+
return unless stdin.tty?
|
40
40
|
|
41
41
|
if echo?
|
42
|
-
|
42
|
+
stdin.gets
|
43
43
|
else
|
44
|
-
|
44
|
+
stdin.noecho(&:gets).tap { $stdout.print "\n" }
|
45
45
|
end
|
46
46
|
rescue Errno::EIO
|
47
47
|
# when stdio gets closed
|
@@ -49,7 +49,11 @@ module Capistrano
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def question
|
52
|
-
if default.nil?
|
52
|
+
if prompt && default.nil?
|
53
|
+
I18n.t(:question_prompt, key: prompt, scope: :capistrano)
|
54
|
+
elsif prompt
|
55
|
+
I18n.t(:question_prompt_default, key: prompt, default_value: default, scope: :capistrano)
|
56
|
+
elsif default.nil?
|
53
57
|
I18n.t(:question, key: key, scope: :capistrano)
|
54
58
|
else
|
55
59
|
I18n.t(:question_default, key: key, default_value: default, scope: :capistrano)
|
@@ -59,6 +63,14 @@ module Capistrano
|
|
59
63
|
def echo?
|
60
64
|
(options || {}).fetch(:echo, true)
|
61
65
|
end
|
66
|
+
|
67
|
+
def stdin
|
68
|
+
(options || {}).fetch(:stdin, $stdin)
|
69
|
+
end
|
70
|
+
|
71
|
+
def prompt
|
72
|
+
(options || {}).fetch(:prompt, nil)
|
73
|
+
end
|
62
74
|
end
|
63
75
|
end
|
64
76
|
end
|
data/lib/capistrano/dsl.rb
CHANGED
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,6 +18,8 @@ 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
|
@@ -58,6 +60,10 @@ class Capistrano::SCM::Git < Capistrano::SCM::Plugin
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
63
|
+
def verify_commit
|
64
|
+
git :"verify-commit", fetch_revision
|
65
|
+
end
|
66
|
+
|
61
67
|
def archive_to_release_path
|
62
68
|
if (tree = fetch(:repo_tree))
|
63
69
|
tree = tree.slice %r#^/?(.*?)/?$#, 1
|
@@ -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
|
@@ -168,8 +168,9 @@ namespace :deploy do
|
|
168
168
|
debug t(:no_current_release, host: host.to_s)
|
169
169
|
end
|
170
170
|
if directories.any?
|
171
|
-
|
172
|
-
|
171
|
+
directories.each_slice(100) do |directories_batch|
|
172
|
+
execute :rm, "-rf", *directories_batch
|
173
|
+
end
|
173
174
|
else
|
174
175
|
info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
|
175
176
|
end
|
data/lib/capistrano/version.rb
CHANGED
@@ -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
|
@@ -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
|
@@ -24,12 +25,12 @@ module Capistrano
|
|
24
25
|
expect { resolver.resolve }.to output(/will not load the git scm/i).to_stderr
|
25
26
|
end
|
26
27
|
|
27
|
-
it "activates the git scm" do
|
28
|
+
it "activates the git scm", capture_io: true do
|
28
29
|
resolver.resolve
|
29
30
|
expect(Rake::Task["git:wrapper"]).not_to be_nil
|
30
31
|
end
|
31
32
|
|
32
|
-
it "sets :scm to :git" do
|
33
|
+
it "sets :scm to :git", capture_io: true do
|
33
34
|
resolver.resolve
|
34
35
|
expect(fetch(:scm)).to eq(:git)
|
35
36
|
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
|