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.
- checksums.yaml +5 -5
- data/.circleci/config.yml +129 -0
- data/.github/issue_template.md +19 -0
- data/.github/pull_request_template.md +22 -0
- data/.github/release-drafter.yml +17 -0
- data/.github/workflows/push.yml +12 -0
- data/.gitignore +8 -5
- data/.rubocop.yml +62 -0
- data/CHANGELOG.md +1 -307
- data/CONTRIBUTING.md +63 -93
- data/DEVELOPMENT.md +127 -0
- data/Dangerfile +1 -0
- data/Gemfile +40 -3
- data/LICENSE.txt +1 -1
- data/README.md +127 -44
- data/RELEASING.md +17 -0
- data/Rakefile +13 -2
- data/UPGRADING-3.7.md +86 -0
- data/bin/cap +1 -1
- data/capistrano.gemspec +21 -24
- data/features/deploy.feature +35 -1
- data/features/doctor.feature +11 -0
- data/features/installation.feature +8 -3
- data/features/stage_failure.feature +9 -0
- data/features/step_definitions/assertions.rb +51 -18
- data/features/step_definitions/cap_commands.rb +9 -0
- data/features/step_definitions/setup.rb +53 -9
- data/features/subdirectory.feature +9 -0
- data/features/support/env.rb +5 -5
- data/features/support/remote_command_helpers.rb +12 -6
- data/features/support/vagrant_helpers.rb +17 -11
- data/lib/Capfile +1 -1
- data/lib/capistrano/all.rb +10 -10
- data/lib/capistrano/application.rb +47 -34
- data/lib/capistrano/configuration/empty_filter.rb +9 -0
- data/lib/capistrano/configuration/filter.rb +17 -47
- data/lib/capistrano/configuration/host_filter.rb +29 -0
- data/lib/capistrano/configuration/null_filter.rb +9 -0
- data/lib/capistrano/configuration/plugin_installer.rb +51 -0
- data/lib/capistrano/configuration/question.rb +31 -9
- data/lib/capistrano/configuration/role_filter.rb +29 -0
- data/lib/capistrano/configuration/scm_resolver.rb +149 -0
- data/lib/capistrano/configuration/server.rb +29 -23
- data/lib/capistrano/configuration/servers.rb +21 -14
- data/lib/capistrano/configuration/validated_variables.rb +110 -0
- data/lib/capistrano/configuration/variables.rb +112 -0
- data/lib/capistrano/configuration.rb +91 -44
- data/lib/capistrano/defaults.rb +26 -4
- data/lib/capistrano/deploy.rb +1 -1
- 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/servers_doctor.rb +105 -0
- data/lib/capistrano/doctor/variables_doctor.rb +74 -0
- data/lib/capistrano/doctor.rb +6 -0
- data/lib/capistrano/dotfile.rb +1 -2
- data/lib/capistrano/dsl/env.rb +9 -47
- data/lib/capistrano/dsl/paths.rb +11 -25
- data/lib/capistrano/dsl/stages.rb +14 -2
- data/lib/capistrano/dsl/task_enhancements.rb +7 -12
- data/lib/capistrano/dsl.rb +47 -16
- data/lib/capistrano/framework.rb +1 -1
- data/lib/capistrano/i18n.rb +32 -24
- data/lib/capistrano/immutable_task.rb +30 -0
- data/lib/capistrano/install.rb +1 -1
- data/lib/capistrano/plugin.rb +95 -0
- data/lib/capistrano/proc_helpers.rb +13 -0
- data/lib/capistrano/scm/git.rb +100 -0
- data/lib/capistrano/scm/hg.rb +55 -0
- data/lib/capistrano/scm/plugin.rb +13 -0
- data/lib/capistrano/scm/svn.rb +56 -0
- data/lib/capistrano/scm/tasks/git.rake +73 -0
- data/lib/capistrano/scm/tasks/hg.rake +53 -0
- data/lib/capistrano/scm/tasks/svn.rake +53 -0
- data/lib/capistrano/scm.rb +7 -20
- data/lib/capistrano/setup.rb +20 -6
- data/lib/capistrano/tasks/console.rake +4 -8
- data/lib/capistrano/tasks/deploy.rake +105 -73
- data/lib/capistrano/tasks/doctor.rake +24 -0
- data/lib/capistrano/tasks/framework.rake +13 -14
- data/lib/capistrano/tasks/install.rake +14 -15
- data/lib/capistrano/templates/Capfile +21 -10
- data/lib/capistrano/templates/deploy.rb.erb +17 -26
- data/lib/capistrano/templates/stage.rb.erb +9 -9
- data/lib/capistrano/upload_task.rb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/lib/capistrano/version_validator.rb +5 -10
- data/spec/integration/dsl_spec.rb +289 -240
- data/spec/integration_spec_helper.rb +3 -5
- data/spec/lib/capistrano/application_spec.rb +23 -39
- data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/filter_spec.rb +83 -85
- data/spec/lib/capistrano/configuration/host_filter_spec.rb +71 -0
- data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/plugin_installer_spec.rb +98 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +58 -26
- data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
- data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +55 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +106 -113
- data/spec/lib/capistrano/configuration/servers_spec.rb +129 -145
- data/spec/lib/capistrano/configuration_spec.rb +224 -63
- data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
- data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +67 -0
- data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
- data/spec/lib/capistrano/doctor/servers_doctor_spec.rb +86 -0
- data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +89 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +97 -59
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +57 -37
- data/spec/lib/capistrano/dsl_spec.rb +84 -11
- data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
- data/spec/lib/capistrano/plugin_spec.rb +84 -0
- data/spec/lib/capistrano/scm/git_spec.rb +184 -0
- data/spec/lib/capistrano/scm/hg_spec.rb +109 -0
- data/spec/lib/capistrano/scm/svn_spec.rb +137 -0
- data/spec/lib/capistrano/scm_spec.rb +7 -8
- data/spec/lib/capistrano/upload_task_spec.rb +7 -7
- data/spec/lib/capistrano/version_validator_spec.rb +61 -46
- data/spec/lib/capistrano_spec.rb +2 -3
- data/spec/spec_helper.rb +21 -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 +64 -39
- metadata +100 -55
- data/.travis.yml +0 -13
- data/features/remote_file_task.feature +0 -14
- data/lib/capistrano/git.rb +0 -46
- data/lib/capistrano/hg.rb +0 -43
- data/lib/capistrano/svn.rb +0 -38
- data/lib/capistrano/tasks/git.rake +0 -81
- data/lib/capistrano/tasks/hg.rake +0 -52
- data/lib/capistrano/tasks/svn.rake +0 -52
- data/spec/lib/capistrano/git_spec.rb +0 -81
- data/spec/lib/capistrano/hg_spec.rb +0 -81
- data/spec/lib/capistrano/svn_spec.rb +0 -79
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
module Capistrano
|
|
2
2
|
class Application < Rake::Application
|
|
3
|
-
|
|
4
3
|
def initialize
|
|
5
4
|
super
|
|
6
|
-
@rakefiles = %w{capfile Capfile capfile.rb Capfile.rb}
|
|
5
|
+
@rakefiles = %w{capfile Capfile capfile.rb Capfile.rb}
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
def name
|
|
@@ -21,11 +20,11 @@ module Capistrano
|
|
|
21
20
|
switch =~ /--#{Regexp.union(not_applicable_to_capistrano)}/
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
super.push(version, dry_run, roles, hostfilter)
|
|
23
|
+
super.push(version, dry_run, roles, hostfilter, print_config_variables)
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
def handle_options
|
|
28
|
-
options.rakelib = [
|
|
27
|
+
options.rakelib = ["rakelib"]
|
|
29
28
|
options.trace_output = $stderr
|
|
30
29
|
|
|
31
30
|
OptionParser.new do |opts|
|
|
@@ -48,11 +47,10 @@ module Capistrano
|
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
standard_rake_options.each { |args| opts.on(*args) }
|
|
51
|
-
opts.environment(
|
|
50
|
+
opts.environment("RAKEOPT")
|
|
52
51
|
end.parse!
|
|
53
52
|
end
|
|
54
53
|
|
|
55
|
-
|
|
56
54
|
def top_level_tasks
|
|
57
55
|
if tasks_without_stage_dependency.include?(@top_level_tasks.first)
|
|
58
56
|
@top_level_tasks
|
|
@@ -63,13 +61,10 @@ module Capistrano
|
|
|
63
61
|
|
|
64
62
|
def display_error_message(ex)
|
|
65
63
|
unless options.backtrace
|
|
66
|
-
|
|
67
|
-
whitelist = (@imported.dup << loc[0]).map{|f| File.absolute_path(f, loc[1])}
|
|
68
|
-
pattern = %r@^(?!#{whitelist.map{|p| Regexp.quote(p)}.join('|')})@
|
|
69
|
-
Rake.application.options.suppress_backtrace_pattern = pattern
|
|
70
|
-
end
|
|
64
|
+
Rake.application.options.suppress_backtrace_pattern = backtrace_pattern if backtrace_pattern
|
|
71
65
|
trace "(Backtrace restricted to imported tasks)"
|
|
72
66
|
end
|
|
67
|
+
|
|
73
68
|
super
|
|
74
69
|
end
|
|
75
70
|
|
|
@@ -81,60 +76,78 @@ module Capistrano
|
|
|
81
76
|
end
|
|
82
77
|
end
|
|
83
78
|
|
|
79
|
+
# allows the `cap install` task to load without a capfile
|
|
80
|
+
def find_rakefile_location
|
|
81
|
+
if (location = super).nil?
|
|
82
|
+
[capfile, Dir.pwd]
|
|
83
|
+
else
|
|
84
|
+
location
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
84
88
|
private
|
|
85
89
|
|
|
90
|
+
def backtrace_pattern
|
|
91
|
+
loc = Rake.application.find_rakefile_location
|
|
92
|
+
return unless loc
|
|
93
|
+
|
|
94
|
+
whitelist = (@imported.dup << loc[0]).map { |f| File.absolute_path(f, loc[1]) }
|
|
95
|
+
/^(?!#{whitelist.map { |p| Regexp.quote(p) }.join('|')})/
|
|
96
|
+
end
|
|
97
|
+
|
|
86
98
|
def load_imports
|
|
87
|
-
if options.show_tasks
|
|
88
|
-
invoke
|
|
89
|
-
set(:stage,
|
|
99
|
+
if options.show_tasks && Rake::Task.task_defined?("load:defaults")
|
|
100
|
+
invoke "load:defaults"
|
|
101
|
+
set(:stage, "")
|
|
90
102
|
Dir[deploy_config_path].each { |f| add_import f }
|
|
91
103
|
end
|
|
92
104
|
|
|
93
105
|
super
|
|
94
106
|
end
|
|
95
107
|
|
|
96
|
-
# allows the `cap install` task to load without a capfile
|
|
97
108
|
def capfile
|
|
98
|
-
File.expand_path(File.join(File.dirname(__FILE__),
|
|
109
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", "Capfile"))
|
|
99
110
|
end
|
|
100
111
|
|
|
101
112
|
def version
|
|
102
|
-
[
|
|
113
|
+
["--version", "-V",
|
|
103
114
|
"Display the program version.",
|
|
104
|
-
lambda
|
|
105
|
-
puts "Capistrano Version: #{Capistrano::VERSION} (Rake Version: #{
|
|
115
|
+
lambda do |_value|
|
|
116
|
+
puts "Capistrano Version: #{Capistrano::VERSION} (Rake Version: #{Rake::VERSION})"
|
|
106
117
|
exit
|
|
107
|
-
|
|
108
|
-
]
|
|
118
|
+
end]
|
|
109
119
|
end
|
|
110
120
|
|
|
111
121
|
def dry_run
|
|
112
|
-
[
|
|
122
|
+
["--dry-run", "-n",
|
|
113
123
|
"Do a dry run without executing actions",
|
|
114
|
-
lambda
|
|
124
|
+
lambda do |_value|
|
|
115
125
|
Configuration.env.set(:sshkit_backend, SSHKit::Backend::Printer)
|
|
116
|
-
|
|
117
|
-
]
|
|
126
|
+
end]
|
|
118
127
|
end
|
|
119
128
|
|
|
120
129
|
def roles
|
|
121
|
-
[
|
|
130
|
+
["--roles ROLES", "-r",
|
|
122
131
|
"Run SSH commands only on hosts matching these roles",
|
|
123
|
-
lambda
|
|
132
|
+
lambda do |value|
|
|
124
133
|
Configuration.env.add_cmdline_filter(:role, value)
|
|
125
|
-
|
|
126
|
-
]
|
|
134
|
+
end]
|
|
127
135
|
end
|
|
128
136
|
|
|
129
137
|
def hostfilter
|
|
130
|
-
[
|
|
138
|
+
["--hosts HOSTS", "-z",
|
|
131
139
|
"Run SSH commands only on matching hosts",
|
|
132
|
-
lambda
|
|
140
|
+
lambda do |value|
|
|
133
141
|
Configuration.env.add_cmdline_filter(:host, value)
|
|
134
|
-
|
|
135
|
-
]
|
|
142
|
+
end]
|
|
136
143
|
end
|
|
137
144
|
|
|
145
|
+
def print_config_variables
|
|
146
|
+
["--print-config-variables", "-p",
|
|
147
|
+
"Display the defined config variables before starting the deployment tasks.",
|
|
148
|
+
lambda do |_value|
|
|
149
|
+
Configuration.env.set(:print_config_variables, true)
|
|
150
|
+
end]
|
|
151
|
+
end
|
|
138
152
|
end
|
|
139
|
-
|
|
140
153
|
end
|
|
@@ -1,55 +1,25 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "capistrano/configuration"
|
|
2
|
+
require "capistrano/configuration/empty_filter"
|
|
3
|
+
require "capistrano/configuration/host_filter"
|
|
4
|
+
require "capistrano/configuration/null_filter"
|
|
5
|
+
require "capistrano/configuration/role_filter"
|
|
2
6
|
|
|
3
7
|
module Capistrano
|
|
4
8
|
class Configuration
|
|
5
9
|
class Filter
|
|
6
|
-
def initialize
|
|
7
|
-
raise "Invalid filter type #{type}" unless
|
|
8
|
-
av = Array(values)
|
|
9
|
-
@
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
when :host
|
|
16
|
-
av.map!{|v| (v.is_a?(String) && v =~ /^(?<name>[-A-Za-z0-9.]+)(,\g<name>)*$/) ? v.split(',') : v }
|
|
17
|
-
av.flatten!
|
|
18
|
-
av.map! do |v|
|
|
19
|
-
case v
|
|
20
|
-
when Regexp then v
|
|
21
|
-
else
|
|
22
|
-
vs = v.to_s
|
|
23
|
-
vs =~ /^[-A-Za-z0-9.]+$/ ? vs : Regexp.new(vs)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
Regexp.union av
|
|
27
|
-
when :role
|
|
28
|
-
av.map!{|v| v.is_a?(String) ? v.split(',') : v }
|
|
29
|
-
av.flatten!
|
|
30
|
-
av.map! do |v|
|
|
31
|
-
case v
|
|
32
|
-
when Regexp then v
|
|
33
|
-
else
|
|
34
|
-
vs = v.to_s
|
|
35
|
-
vs =~ %r{^/(.+)/$} ? Regexp.new($1) : %r{^#{vs}$}
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
Regexp.union av
|
|
39
|
-
else
|
|
40
|
-
nil
|
|
41
|
-
end
|
|
10
|
+
def initialize(type, values=nil)
|
|
11
|
+
raise "Invalid filter type #{type}" unless %i(host role).include? type
|
|
12
|
+
av = Array(values)
|
|
13
|
+
@strategy = if av.empty? then EmptyFilter.new
|
|
14
|
+
elsif av.include?(:all) || av.include?("all") then NullFilter.new
|
|
15
|
+
elsif type == :host then HostFilter.new(values)
|
|
16
|
+
elsif type == :role then RoleFilter.new(values)
|
|
17
|
+
else NullFilter.new
|
|
18
|
+
end
|
|
42
19
|
end
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
when :none then return []
|
|
47
|
-
when :all then return servers
|
|
48
|
-
when :host
|
|
49
|
-
as.select {|s| @rex.match s.hostname}
|
|
50
|
-
when :role
|
|
51
|
-
as.select {|s| s.roles.any? {|r| @rex.match r} }
|
|
52
|
-
end
|
|
20
|
+
|
|
21
|
+
def filter(servers)
|
|
22
|
+
@strategy.filter servers
|
|
53
23
|
end
|
|
54
24
|
end
|
|
55
25
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class Configuration
|
|
3
|
+
class HostFilter
|
|
4
|
+
def initialize(values)
|
|
5
|
+
av = Array(values).dup
|
|
6
|
+
av = av.flat_map { |v| v.is_a?(String) && v =~ /^(?<name>[-A-Za-z0-9.]+)(,\g<name>)*$/ ? v.split(",") : v }
|
|
7
|
+
@rex = regex_matcher(av)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def filter(servers)
|
|
11
|
+
Array(servers).select { |s| @rex.match s.to_s }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def regex_matcher(values)
|
|
17
|
+
values.map! do |v|
|
|
18
|
+
case v
|
|
19
|
+
when Regexp then v
|
|
20
|
+
else
|
|
21
|
+
vs = v.to_s
|
|
22
|
+
vs =~ /^[-A-Za-z0-9.]+$/ ? /^#{Regexp.quote(vs)}$/ : Regexp.new(vs)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
Regexp.union values
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Encapsulates the logic for installing plugins into Capistrano. Plugins must
|
|
2
|
+
# simply conform to a basic API; the PluginInstaller takes care of invoking the
|
|
3
|
+
# API at appropriate times.
|
|
4
|
+
#
|
|
5
|
+
# This class is not used directly; instead it is typically accessed via the
|
|
6
|
+
# `install_plugin` method of the Capistrano DSL.
|
|
7
|
+
#
|
|
8
|
+
module Capistrano
|
|
9
|
+
class Configuration
|
|
10
|
+
class PluginInstaller
|
|
11
|
+
# "Installs" a Plugin into Capistrano by loading its tasks, hooks, and
|
|
12
|
+
# defaults at the appropriate time. The hooks in particular can be
|
|
13
|
+
# skipped, if you want full control over when and how the plugin's tasks
|
|
14
|
+
# are executed. Simply pass `load_hooks:false` to opt out.
|
|
15
|
+
#
|
|
16
|
+
# The plugin class or instance may be provided. These are equivalent:
|
|
17
|
+
#
|
|
18
|
+
# install(Capistrano::SCM::Git)
|
|
19
|
+
# install(Capistrano::SCM::Git.new)
|
|
20
|
+
#
|
|
21
|
+
# Note that the :load_immediately flag is for internal use only and will
|
|
22
|
+
# be removed in an upcoming release.
|
|
23
|
+
#
|
|
24
|
+
def install(plugin, load_hooks: true, load_immediately: false)
|
|
25
|
+
plugin = plugin.is_a?(Class) ? plugin.new : plugin
|
|
26
|
+
|
|
27
|
+
plugin.define_tasks
|
|
28
|
+
plugin.register_hooks if load_hooks
|
|
29
|
+
@scm_installed ||= provides_scm?(plugin)
|
|
30
|
+
|
|
31
|
+
if load_immediately
|
|
32
|
+
plugin.set_defaults
|
|
33
|
+
else
|
|
34
|
+
Rake::Task.define_task("load:defaults") do
|
|
35
|
+
plugin.set_defaults
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def scm_installed?
|
|
41
|
+
@scm_installed
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def provides_scm?(plugin)
|
|
47
|
+
plugin.respond_to?(:scm?) && plugin.scm?
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
module Capistrano
|
|
2
2
|
class Configuration
|
|
3
3
|
class Question
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@
|
|
4
|
+
def initialize(key, default, options={})
|
|
5
|
+
@key = key
|
|
6
|
+
@default = default
|
|
7
|
+
@options = options
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
def call
|
|
@@ -12,10 +13,12 @@ module Capistrano
|
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
private
|
|
16
|
+
|
|
15
17
|
attr_reader :key, :default, :options
|
|
16
18
|
|
|
17
19
|
def ask_question
|
|
18
20
|
$stdout.print question
|
|
21
|
+
$stdout.flush
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
def value_or_default
|
|
@@ -28,27 +31,46 @@ module Capistrano
|
|
|
28
31
|
|
|
29
32
|
def response
|
|
30
33
|
return @response if defined? @response
|
|
31
|
-
|
|
34
|
+
|
|
32
35
|
@response = (gets || "").chomp
|
|
33
36
|
end
|
|
34
|
-
|
|
37
|
+
|
|
35
38
|
def gets
|
|
39
|
+
return unless stdin.tty?
|
|
40
|
+
|
|
36
41
|
if echo?
|
|
37
|
-
|
|
42
|
+
stdin.gets
|
|
38
43
|
else
|
|
39
|
-
|
|
44
|
+
stdin.noecho(&:gets).tap { $stdout.print "\n" }
|
|
40
45
|
end
|
|
41
46
|
rescue Errno::EIO
|
|
42
47
|
# when stdio gets closed
|
|
48
|
+
return
|
|
43
49
|
end
|
|
44
|
-
|
|
50
|
+
|
|
45
51
|
def question
|
|
46
|
-
|
|
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?
|
|
57
|
+
I18n.t(:question, key: key, scope: :capistrano)
|
|
58
|
+
else
|
|
59
|
+
I18n.t(:question_default, key: key, default_value: default, scope: :capistrano)
|
|
60
|
+
end
|
|
47
61
|
end
|
|
48
62
|
|
|
49
63
|
def echo?
|
|
50
64
|
(options || {}).fetch(:echo, true)
|
|
51
65
|
end
|
|
66
|
+
|
|
67
|
+
def stdin
|
|
68
|
+
(options || {}).fetch(:stdin, $stdin)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def prompt
|
|
72
|
+
(options || {}).fetch(:prompt, nil)
|
|
73
|
+
end
|
|
52
74
|
end
|
|
53
75
|
end
|
|
54
76
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class Configuration
|
|
3
|
+
class RoleFilter
|
|
4
|
+
def initialize(values)
|
|
5
|
+
av = Array(values).dup
|
|
6
|
+
av = av.flat_map { |v| v.is_a?(String) ? v.split(",") : v }
|
|
7
|
+
@rex = regex_matcher(av)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def filter(servers)
|
|
11
|
+
Array(servers).select { |s| s.is_a?(String) ? false : s.roles.any? { |r| @rex.match r } }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def regex_matcher(values)
|
|
17
|
+
values.map! do |v|
|
|
18
|
+
case v
|
|
19
|
+
when Regexp then v
|
|
20
|
+
else
|
|
21
|
+
vs = v.to_s
|
|
22
|
+
vs =~ %r{^/(.+)/$} ? Regexp.new($1) : /^#{Regexp.quote(vs)}$/
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
Regexp.union values
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class Configuration
|
|
3
|
+
# In earlier versions of Capistrano, users would specify the desired SCM
|
|
4
|
+
# implementation using `set :scm, :git`, for example. Capistrano would then
|
|
5
|
+
# load the matching .rb file based on this variable.
|
|
6
|
+
#
|
|
7
|
+
# Now we expect users to explicitly `require` and call `new` on the desired
|
|
8
|
+
# SCM implementation in their Capfile. The `set` technique is deprecated.
|
|
9
|
+
#
|
|
10
|
+
# This SCMResolver class takes care of managing the transition from the old
|
|
11
|
+
# to new system. It maintains the legacy behavior, but prints deprecation
|
|
12
|
+
# warnings when it is used.
|
|
13
|
+
#
|
|
14
|
+
# To maintain backwards compatibility, the resolver will load the Git SCM by
|
|
15
|
+
# if default it determines that no SCM has been explicitly specified or
|
|
16
|
+
# loaded. To force no SCM to be used at all, use `set :scm, nil`. This hack
|
|
17
|
+
# won't be necessary once backwards compatibility is removed in a future
|
|
18
|
+
# version.
|
|
19
|
+
#
|
|
20
|
+
# TODO: Remove this class entirely in Capistrano 4.0.
|
|
21
|
+
#
|
|
22
|
+
class SCMResolver
|
|
23
|
+
DEFAULT_GIT = :"default-git"
|
|
24
|
+
|
|
25
|
+
include Capistrano::DSL
|
|
26
|
+
|
|
27
|
+
def resolve
|
|
28
|
+
return if scm_name.nil?
|
|
29
|
+
set(:scm, :git) if using_default_scm?
|
|
30
|
+
|
|
31
|
+
print_deprecation_warnings_if_applicable
|
|
32
|
+
|
|
33
|
+
# Note that `scm_plugin_installed?` comes from Capistrano::DSL
|
|
34
|
+
if scm_plugin_installed?
|
|
35
|
+
delete(:scm)
|
|
36
|
+
return
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if built_in_scm_name?
|
|
40
|
+
load_built_in_scm
|
|
41
|
+
else
|
|
42
|
+
# Compatibility with existing 3.x third-party SCMs
|
|
43
|
+
register_legacy_scm_hooks
|
|
44
|
+
load_legacy_scm_by_name
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def using_default_scm?
|
|
51
|
+
return @using_default_scm if defined? @using_default_scm
|
|
52
|
+
@using_default_scm = (fetch(:scm) == DEFAULT_GIT)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def scm_name
|
|
56
|
+
fetch(:scm)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def load_built_in_scm
|
|
60
|
+
require "capistrano/scm/#{scm_name}"
|
|
61
|
+
scm_class = Object.const_get(built_in_scm_plugin_class_name)
|
|
62
|
+
# We use :load_immediately because we are initializing the SCM plugin
|
|
63
|
+
# late in the load process and therefore can't use the standard
|
|
64
|
+
# load:defaults technique.
|
|
65
|
+
install_plugin(scm_class, load_immediately: true)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def load_legacy_scm_by_name
|
|
69
|
+
load("capistrano/#{scm_name}.rb")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def third_party_scm_name?
|
|
73
|
+
!built_in_scm_name?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def built_in_scm_name?
|
|
77
|
+
%w(git hg svn).include?(scm_name.to_s.downcase)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def built_in_scm_plugin_class_name
|
|
81
|
+
"Capistrano::SCM::#{scm_name.to_s.capitalize}"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# rubocop:disable Style/GuardClause
|
|
85
|
+
def register_legacy_scm_hooks
|
|
86
|
+
if Rake::Task.task_defined?("deploy:new_release_path")
|
|
87
|
+
after "deploy:new_release_path", "#{scm_name}:create_release"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if Rake::Task.task_defined?("deploy:check")
|
|
91
|
+
before "deploy:check", "#{scm_name}:check"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if Rake::Task.task_defined?("deploy:set_current_revision")
|
|
95
|
+
before "deploy:set_current_revision",
|
|
96
|
+
"#{scm_name}:set_current_revision"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
# rubocop:enable Style/GuardClause
|
|
100
|
+
|
|
101
|
+
def print_deprecation_warnings_if_applicable
|
|
102
|
+
if using_default_scm?
|
|
103
|
+
warn_add_git_to_capfile unless scm_plugin_installed?
|
|
104
|
+
elsif built_in_scm_name?
|
|
105
|
+
warn_set_scm_is_deprecated
|
|
106
|
+
elsif third_party_scm_name?
|
|
107
|
+
warn_third_party_scm_must_be_upgraded
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def warn_set_scm_is_deprecated
|
|
112
|
+
$stderr.puts(<<-MESSAGE)
|
|
113
|
+
[Deprecation Notice] `set :scm, #{scm_name.inspect}` is deprecated.
|
|
114
|
+
To ensure your project is compatible with future versions of Capistrano,
|
|
115
|
+
remove the :scm setting and instead add these lines to your Capfile after
|
|
116
|
+
`require "capistrano/deploy"`:
|
|
117
|
+
|
|
118
|
+
require "capistrano/scm/#{scm_name}"
|
|
119
|
+
install_plugin #{built_in_scm_plugin_class_name}
|
|
120
|
+
|
|
121
|
+
MESSAGE
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def warn_add_git_to_capfile
|
|
125
|
+
$stderr.puts(<<-MESSAGE)
|
|
126
|
+
[Deprecation Notice] Future versions of Capistrano will not load the Git SCM
|
|
127
|
+
plugin by default. To silence this deprecation warning, add the following to
|
|
128
|
+
your Capfile after `require "capistrano/deploy"`:
|
|
129
|
+
|
|
130
|
+
require "capistrano/scm/git"
|
|
131
|
+
install_plugin Capistrano::SCM::Git
|
|
132
|
+
|
|
133
|
+
MESSAGE
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def warn_third_party_scm_must_be_upgraded
|
|
137
|
+
$stderr.puts(<<-MESSAGE)
|
|
138
|
+
[Deprecation Notice] `set :scm, #{scm_name.inspect}` is deprecated.
|
|
139
|
+
To ensure this custom SCM will work with future versions of Capistrano,
|
|
140
|
+
please upgrade it to a version that uses the new SCM plugin mechanism
|
|
141
|
+
documented here:
|
|
142
|
+
|
|
143
|
+
http://capistranorb.com/documentation/advanced-features/custom-scm
|
|
144
|
+
|
|
145
|
+
MESSAGE
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|