capistrano 2.8.0 → 3.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- 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/issue_template.md +19 -0
- data/.github/pull_request_template.md +22 -0
- data/.github/release-drafter.yml +25 -0
- data/.github/workflows/ci.yml +80 -0
- data/.github/workflows/release-drafter.yml +18 -0
- data/.gitignore +23 -8
- data/.rubocop.yml +62 -0
- data/CHANGELOG.md +1 -0
- data/CONTRIBUTING.md +63 -0
- data/DEVELOPMENT.md +112 -0
- data/Gemfile +42 -9
- data/LICENSE.txt +21 -0
- data/README.md +221 -0
- data/RELEASING.md +17 -0
- data/Rakefile +17 -8
- data/UPGRADING-3.7.md +86 -0
- data/bin/cap +2 -3
- data/bin/capify +7 -89
- data/capistrano.gemspec +29 -43
- data/docker-compose.yml +8 -0
- data/features/configuration.feature +28 -0
- data/features/deploy.feature +92 -0
- data/features/deploy_failure.feature +17 -0
- data/features/doctor.feature +11 -0
- data/features/installation.feature +21 -0
- data/features/sshconnect.feature +11 -0
- data/features/stage_failure.feature +9 -0
- data/features/step_definitions/assertions.rb +162 -0
- data/features/step_definitions/cap_commands.rb +21 -0
- data/features/step_definitions/setup.rb +91 -0
- data/features/subdirectory.feature +9 -0
- data/features/support/docker_gateway.rb +53 -0
- data/features/support/env.rb +1 -0
- data/features/support/remote_command_helpers.rb +29 -0
- data/features/support/remote_ssh_helpers.rb +33 -0
- data/lib/Capfile +3 -0
- data/lib/capistrano/all.rb +17 -0
- data/lib/capistrano/application.rb +153 -0
- data/lib/capistrano/configuration/empty_filter.rb +9 -0
- data/lib/capistrano/configuration/filter.rb +26 -0
- 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 +76 -0
- data/lib/capistrano/configuration/role_filter.rb +29 -0
- data/lib/capistrano/configuration/scm_resolver.rb +149 -0
- data/lib/capistrano/configuration/server.rb +137 -0
- data/lib/capistrano/configuration/servers.rb +56 -96
- data/lib/capistrano/configuration/validated_variables.rb +110 -0
- data/lib/capistrano/configuration/variables.rb +79 -94
- data/lib/capistrano/configuration.rb +178 -33
- data/lib/capistrano/console.rb +1 -0
- data/lib/capistrano/defaults.rb +36 -0
- data/lib/capistrano/deploy.rb +3 -0
- data/lib/capistrano/doctor/environment_doctor.rb +19 -0
- data/lib/capistrano/doctor/gems_doctor.rb +45 -0
- data/lib/capistrano/doctor/output_helpers.rb +79 -0
- data/lib/capistrano/doctor/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 +2 -0
- data/lib/capistrano/dsl/env.rb +43 -0
- data/lib/capistrano/dsl/paths.rb +89 -0
- data/lib/capistrano/dsl/stages.rb +31 -0
- data/lib/capistrano/dsl/task_enhancements.rb +61 -0
- data/lib/capistrano/dsl.rb +95 -0
- data/lib/capistrano/framework.rb +2 -0
- data/lib/capistrano/i18n.rb +46 -0
- data/lib/capistrano/immutable_task.rb +30 -0
- data/lib/capistrano/install.rb +1 -0
- data/lib/capistrano/plugin.rb +95 -0
- data/lib/capistrano/proc_helpers.rb +13 -0
- data/lib/capistrano/scm/git.rb +105 -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 +84 -0
- data/lib/capistrano/scm/tasks/hg.rake +53 -0
- data/lib/capistrano/scm/tasks/svn.rake +53 -0
- data/lib/capistrano/scm.rb +115 -0
- data/lib/capistrano/setup.rb +36 -0
- data/lib/capistrano/tasks/console.rake +25 -0
- data/lib/capistrano/tasks/deploy.rake +280 -0
- data/lib/capistrano/tasks/doctor.rake +24 -0
- data/lib/capistrano/tasks/framework.rake +67 -0
- data/lib/capistrano/tasks/install.rake +41 -0
- data/lib/capistrano/templates/Capfile +38 -0
- data/lib/capistrano/templates/deploy.rb.erb +39 -0
- data/lib/capistrano/templates/stage.rb.erb +61 -0
- data/lib/capistrano/upload_task.rb +9 -0
- data/lib/capistrano/version.rb +1 -14
- data/lib/capistrano/version_validator.rb +32 -0
- data/lib/capistrano.rb +0 -3
- data/spec/integration/dsl_spec.rb +632 -0
- data/spec/integration_spec_helper.rb +5 -0
- data/spec/lib/capistrano/application_spec.rb +60 -0
- data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/filter_spec.rb +109 -0
- 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 +92 -0
- data/spec/lib/capistrano/configuration/role_filter_spec.rb +80 -0
- data/spec/lib/capistrano/configuration/scm_resolver_spec.rb +56 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +309 -0
- data/spec/lib/capistrano/configuration/servers_spec.rb +331 -0
- data/spec/lib/capistrano/configuration_spec.rb +357 -0
- 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 +228 -0
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +108 -0
- data/spec/lib/capistrano/dsl_spec.rb +125 -0
- 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 +194 -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 +103 -0
- data/spec/lib/capistrano/upload_task_spec.rb +19 -0
- data/spec/lib/capistrano/version_validator_spec.rb +118 -0
- data/spec/lib/capistrano_spec.rb +7 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/support/tasks/database.rake +11 -0
- data/spec/support/tasks/fail.rake +8 -0
- data/spec/support/tasks/failed.rake +5 -0
- data/spec/support/tasks/plugin.rake +6 -0
- data/spec/support/tasks/root.rake +11 -0
- data/spec/support/test_app.rb +205 -0
- metadata +234 -208
- data/.rvmrc +0 -1
- data/CHANGELOG +0 -954
- data/README.mdown +0 -76
- data/lib/capistrano/callback.rb +0 -45
- data/lib/capistrano/cli/execute.rb +0 -85
- data/lib/capistrano/cli/help.rb +0 -125
- data/lib/capistrano/cli/help.txt +0 -81
- data/lib/capistrano/cli/options.rb +0 -243
- data/lib/capistrano/cli/ui.rb +0 -40
- data/lib/capistrano/cli.rb +0 -47
- data/lib/capistrano/command.rb +0 -286
- data/lib/capistrano/configuration/actions/file_transfer.rb +0 -51
- data/lib/capistrano/configuration/actions/inspect.rb +0 -46
- data/lib/capistrano/configuration/actions/invocation.rb +0 -298
- data/lib/capistrano/configuration/callbacks.rb +0 -148
- data/lib/capistrano/configuration/connections.rb +0 -230
- data/lib/capistrano/configuration/execution.rb +0 -143
- data/lib/capistrano/configuration/loading.rb +0 -197
- data/lib/capistrano/configuration/namespaces.rb +0 -197
- data/lib/capistrano/configuration/roles.rb +0 -73
- data/lib/capistrano/errors.rb +0 -19
- data/lib/capistrano/ext/string.rb +0 -5
- data/lib/capistrano/extensions.rb +0 -57
- data/lib/capistrano/logger.rb +0 -59
- data/lib/capistrano/processable.rb +0 -53
- data/lib/capistrano/recipes/compat.rb +0 -32
- data/lib/capistrano/recipes/deploy/assets.rb +0 -57
- data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
- data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -54
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -111
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
- data/lib/capistrano/recipes/deploy/scm/base.rb +0 -196
- data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
- data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -153
- data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -96
- data/lib/capistrano/recipes/deploy/scm/git.rb +0 -282
- data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -137
- data/lib/capistrano/recipes/deploy/scm/none.rb +0 -44
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -138
- data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -121
- data/lib/capistrano/recipes/deploy/scm.rb +0 -19
- data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -88
- data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -224
- data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
- data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -57
- data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
- data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/recipes/deploy.rb +0 -568
- data/lib/capistrano/recipes/standard.rb +0 -37
- data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/role.rb +0 -102
- data/lib/capistrano/server_definition.rb +0 -56
- data/lib/capistrano/shell.rb +0 -260
- data/lib/capistrano/ssh.rb +0 -101
- data/lib/capistrano/task_definition.rb +0 -75
- data/lib/capistrano/transfer.rb +0 -216
- data/rvmrc.sample +0 -1
- data/test/cli/execute_test.rb +0 -132
- data/test/cli/help_test.rb +0 -165
- data/test/cli/options_test.rb +0 -329
- data/test/cli/ui_test.rb +0 -28
- data/test/cli_test.rb +0 -17
- data/test/command_test.rb +0 -289
- data/test/configuration/actions/file_transfer_test.rb +0 -61
- data/test/configuration/actions/inspect_test.rb +0 -65
- data/test/configuration/actions/invocation_test.rb +0 -247
- data/test/configuration/callbacks_test.rb +0 -220
- data/test/configuration/connections_test.rb +0 -420
- data/test/configuration/execution_test.rb +0 -175
- data/test/configuration/loading_test.rb +0 -132
- data/test/configuration/namespace_dsl_test.rb +0 -311
- data/test/configuration/roles_test.rb +0 -144
- data/test/configuration/servers_test.rb +0 -183
- data/test/configuration/variables_test.rb +0 -190
- data/test/configuration_test.rb +0 -88
- data/test/deploy/local_dependency_test.rb +0 -76
- data/test/deploy/remote_dependency_test.rb +0 -135
- data/test/deploy/scm/accurev_test.rb +0 -23
- data/test/deploy/scm/base_test.rb +0 -55
- data/test/deploy/scm/bzr_test.rb +0 -51
- data/test/deploy/scm/darcs_test.rb +0 -37
- data/test/deploy/scm/git_test.rb +0 -184
- data/test/deploy/scm/mercurial_test.rb +0 -134
- data/test/deploy/scm/none_test.rb +0 -35
- data/test/deploy/scm/subversion_test.rb +0 -32
- data/test/deploy/strategy/copy_test.rb +0 -321
- data/test/extensions_test.rb +0 -69
- data/test/fixtures/cli_integration.rb +0 -5
- data/test/fixtures/config.rb +0 -5
- data/test/fixtures/custom.rb +0 -3
- data/test/logger_test.rb +0 -123
- data/test/recipes_test.rb +0 -25
- data/test/role_test.rb +0 -11
- data/test/server_definition_test.rb +0 -121
- data/test/shell_test.rb +0 -90
- data/test/ssh_test.rb +0 -113
- data/test/task_definition_test.rb +0 -116
- data/test/transfer_test.rb +0 -160
- data/test/utils.rb +0 -37
@@ -0,0 +1,110 @@
|
|
1
|
+
require "capistrano/proc_helpers"
|
2
|
+
require "delegate"
|
3
|
+
|
4
|
+
module Capistrano
|
5
|
+
class Configuration
|
6
|
+
# Decorates a Variables object to additionally perform an optional set of
|
7
|
+
# user-supplied validation rules. Each rule for a given key is invoked
|
8
|
+
# immediately whenever `set` is called with a value for that key.
|
9
|
+
#
|
10
|
+
# If `set` is called with a callable value or a block, validation is not
|
11
|
+
# performed immediately. Instead, the validation rules are invoked the first
|
12
|
+
# time `fetch` is used to access the value.
|
13
|
+
#
|
14
|
+
# A rule is simply a block that accepts two arguments: key and value. It is
|
15
|
+
# up to the rule to raise an exception when it deems the value is invalid
|
16
|
+
# (or just print a warning).
|
17
|
+
#
|
18
|
+
# Rules can be registered using the DSL like this:
|
19
|
+
#
|
20
|
+
# validate(:my_key) do |key, value|
|
21
|
+
# # rule goes here
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
class ValidatedVariables < SimpleDelegator
|
25
|
+
include Capistrano::ProcHelpers
|
26
|
+
|
27
|
+
def initialize(variables)
|
28
|
+
super(variables)
|
29
|
+
@validators = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
# Decorate Variables#set to add validation behavior.
|
33
|
+
def set(key, value=nil, &block)
|
34
|
+
assert_value_or_block_not_both(value, block)
|
35
|
+
|
36
|
+
# Skip validation behavior if no validators are registered for this key
|
37
|
+
return super unless validators.key?(key)
|
38
|
+
|
39
|
+
value_to_evaluate = block || value
|
40
|
+
|
41
|
+
if callable_without_parameters?(value_to_evaluate)
|
42
|
+
super(key, assert_valid_later(key, value_to_evaluate), &nil)
|
43
|
+
else
|
44
|
+
assert_valid_now(key, value_to_evaluate)
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Register a validation rule for the given key.
|
50
|
+
def validate(key, &validator)
|
51
|
+
vs = (validators[key] || [])
|
52
|
+
vs << validator
|
53
|
+
validators[key] = vs
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
attr_reader :validators
|
59
|
+
|
60
|
+
# Given a callable that provides a value, wrap the callable with another
|
61
|
+
# object that responds to `call`. This new object will perform validation
|
62
|
+
# and then return the original callable's value.
|
63
|
+
#
|
64
|
+
# If the callable is a `Question`, the object returned by this method will
|
65
|
+
# also be a `Question` (a `ValidatedQuestion`, to be precise). This
|
66
|
+
# ensures that `is_a?(Question)` remains true even after the validation
|
67
|
+
# wrapper is applied. This is needed so that `Configuration#is_question?`
|
68
|
+
# works as expected.
|
69
|
+
#
|
70
|
+
def assert_valid_later(key, callable)
|
71
|
+
validation_callback = proc do
|
72
|
+
value = callable.call
|
73
|
+
assert_valid_now(key, value)
|
74
|
+
value
|
75
|
+
end
|
76
|
+
|
77
|
+
if callable.is_a?(Question)
|
78
|
+
ValidatedQuestion.new(validation_callback)
|
79
|
+
else
|
80
|
+
validation_callback
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Runs all validation rules registered for the given key against the
|
85
|
+
# user-supplied value for that variable. If no validator raises an
|
86
|
+
# exception, the value is assumed to be valid.
|
87
|
+
def assert_valid_now(key, value)
|
88
|
+
validators[key].each do |validator|
|
89
|
+
validator.call(key, value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def assert_value_or_block_not_both(value, block)
|
94
|
+
return if value.nil? || block.nil?
|
95
|
+
raise Capistrano::ValidationError,
|
96
|
+
"Value and block both passed to Configuration#set"
|
97
|
+
end
|
98
|
+
|
99
|
+
class ValidatedQuestion < Question
|
100
|
+
def initialize(validator)
|
101
|
+
@validator = validator
|
102
|
+
end
|
103
|
+
|
104
|
+
def call
|
105
|
+
@validator.call
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -1,126 +1,111 @@
|
|
1
|
-
require
|
1
|
+
require "capistrano/proc_helpers"
|
2
2
|
|
3
3
|
module Capistrano
|
4
4
|
class Configuration
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
# Holds the variables assigned at Capistrano runtime via `set` and retrieved
|
6
|
+
# with `fetch`. Does internal bookkeeping to help identify user mistakes
|
7
|
+
# like spelling errors or unused variables that may lead to unexpected
|
8
|
+
# behavior.
|
9
|
+
class Variables
|
10
|
+
CAPISTRANO_LOCATION = File.expand_path("../..", __FILE__).freeze
|
11
|
+
IGNORED_LOCATIONS = [
|
12
|
+
"#{CAPISTRANO_LOCATION}/configuration/variables.rb:",
|
13
|
+
"#{CAPISTRANO_LOCATION}/configuration.rb:",
|
14
|
+
"#{CAPISTRANO_LOCATION}/dsl/env.rb:",
|
15
|
+
"/dsl.rb:",
|
16
|
+
"/forwardable.rb:"
|
17
|
+
].freeze
|
18
|
+
private_constant :CAPISTRANO_LOCATION, :IGNORED_LOCATIONS
|
19
|
+
|
20
|
+
include Capistrano::ProcHelpers
|
21
|
+
|
22
|
+
def initialize(values={})
|
23
|
+
@trusted_keys = []
|
24
|
+
@fetched_keys = []
|
25
|
+
@locations = {}
|
26
|
+
@values = values
|
27
|
+
@trusted = true
|
13
28
|
end
|
14
29
|
|
15
|
-
|
16
|
-
|
17
|
-
|
30
|
+
def untrusted!
|
31
|
+
@trusted = false
|
32
|
+
yield
|
33
|
+
ensure
|
34
|
+
@trusted = true
|
35
|
+
end
|
18
36
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
37
|
+
def set(key, value=nil, &block)
|
38
|
+
@trusted_keys << key if trusted? && !@trusted_keys.include?(key)
|
39
|
+
remember_location(key)
|
40
|
+
values[key] = block || value
|
41
|
+
trace_set(key)
|
42
|
+
values[key]
|
43
|
+
end
|
24
44
|
|
25
|
-
|
26
|
-
|
27
|
-
|
45
|
+
def fetch(key, default=nil, &block)
|
46
|
+
fetched_keys << key unless fetched_keys.include?(key)
|
47
|
+
peek(key, default, &block)
|
48
|
+
end
|
28
49
|
|
29
|
-
|
30
|
-
|
50
|
+
# Internal use only.
|
51
|
+
def peek(key, default=nil, &block)
|
52
|
+
value = fetch_for(key, default, &block)
|
53
|
+
while callable_without_parameters?(value)
|
54
|
+
value = (values[key] = value.call)
|
31
55
|
end
|
32
|
-
|
33
|
-
value = args.empty? ? block : args.first
|
34
|
-
sym = variable.to_sym
|
35
|
-
protect(sym) { @variables[sym] = value }
|
56
|
+
value
|
36
57
|
end
|
37
58
|
|
38
|
-
|
39
|
-
|
40
|
-
# Removes any trace of the given variable.
|
41
|
-
def unset(variable)
|
42
|
-
sym = variable.to_sym
|
43
|
-
protect(sym) do
|
44
|
-
@original_procs.delete(sym)
|
45
|
-
@variables.delete(sym)
|
46
|
-
end
|
59
|
+
def fetch_for(key, default, &block)
|
60
|
+
block ? values.fetch(key, &block) : values.fetch(key, default)
|
47
61
|
end
|
48
62
|
|
49
|
-
|
50
|
-
|
51
|
-
@variables.key?(variable.to_sym)
|
63
|
+
def delete(key)
|
64
|
+
values.delete(key)
|
52
65
|
end
|
53
66
|
|
54
|
-
|
55
|
-
|
56
|
-
# true if the variable was actually reset.
|
57
|
-
def reset!(variable)
|
58
|
-
sym = variable.to_sym
|
59
|
-
protect(sym) do
|
60
|
-
if @original_procs.key?(sym)
|
61
|
-
@variables[sym] = @original_procs.delete(sym)
|
62
|
-
true
|
63
|
-
else
|
64
|
-
false
|
65
|
-
end
|
66
|
-
end
|
67
|
+
def trusted_keys
|
68
|
+
@trusted_keys.dup
|
67
69
|
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
def fetch(variable, *args)
|
73
|
-
if !args.empty? && block_given?
|
74
|
-
raise ArgumentError, "you must specify either a default value or a block, but not both"
|
75
|
-
end
|
71
|
+
def untrusted_keys
|
72
|
+
keys - @trusted_keys
|
73
|
+
end
|
76
74
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
return args.first unless args.empty?
|
81
|
-
return yield(variable) if block_given?
|
82
|
-
raise IndexError, "`#{variable}' not found"
|
83
|
-
end
|
84
|
-
|
85
|
-
if @variables[sym].respond_to?(:call)
|
86
|
-
@original_procs[sym] = @variables[sym]
|
87
|
-
@variables[sym] = @variables[sym].call
|
88
|
-
end
|
89
|
-
end
|
75
|
+
def keys
|
76
|
+
values.keys
|
77
|
+
end
|
90
78
|
|
91
|
-
|
79
|
+
# Keys that have been set, but which have never been fetched.
|
80
|
+
def unused_keys
|
81
|
+
keys - fetched_keys
|
92
82
|
end
|
93
83
|
|
94
|
-
|
95
|
-
|
84
|
+
# Returns an array of source file location(s) where the given key was
|
85
|
+
# assigned (i.e. where `set` was called). If the key was never assigned,
|
86
|
+
# returns `nil`.
|
87
|
+
def source_locations(key)
|
88
|
+
locations[key]
|
96
89
|
end
|
97
90
|
|
98
|
-
|
99
|
-
initialize_without_variables(*args)
|
100
|
-
@variables = {}
|
101
|
-
@original_procs = {}
|
102
|
-
@variable_locks = Hash.new { |h,k| h[k] = Mutex.new }
|
91
|
+
private
|
103
92
|
|
104
|
-
|
105
|
-
set :logger, logger
|
106
|
-
end
|
107
|
-
private :initialize_with_variables
|
93
|
+
attr_reader :locations, :values, :fetched_keys
|
108
94
|
|
109
|
-
def
|
110
|
-
@
|
95
|
+
def trusted?
|
96
|
+
@trusted
|
111
97
|
end
|
112
|
-
private :protect
|
113
98
|
|
114
|
-
def
|
115
|
-
|
99
|
+
def remember_location(key)
|
100
|
+
location = caller.find do |line|
|
101
|
+
IGNORED_LOCATIONS.none? { |i| line.include?(i) }
|
102
|
+
end
|
103
|
+
(locations[key] ||= []) << location
|
116
104
|
end
|
117
105
|
|
118
|
-
def
|
119
|
-
|
120
|
-
|
121
|
-
else
|
122
|
-
method_missing_without_variables(sym, *args, &block)
|
123
|
-
end
|
106
|
+
def trace_set(key)
|
107
|
+
return unless fetch(:print_config_variables, false)
|
108
|
+
puts "Config variable set: #{key.inspect} => #{values[key].inspect}"
|
124
109
|
end
|
125
110
|
end
|
126
111
|
end
|
@@ -1,44 +1,189 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require 'capistrano/configuration/roles'
|
9
|
-
require 'capistrano/configuration/servers'
|
10
|
-
require 'capistrano/configuration/variables'
|
11
|
-
|
12
|
-
require 'capistrano/configuration/actions/file_transfer'
|
13
|
-
require 'capistrano/configuration/actions/inspect'
|
14
|
-
require 'capistrano/configuration/actions/invocation'
|
1
|
+
require_relative "configuration/filter"
|
2
|
+
require_relative "configuration/question"
|
3
|
+
require_relative "configuration/plugin_installer"
|
4
|
+
require_relative "configuration/server"
|
5
|
+
require_relative "configuration/servers"
|
6
|
+
require_relative "configuration/validated_variables"
|
7
|
+
require_relative "configuration/variables"
|
15
8
|
|
16
9
|
module Capistrano
|
17
|
-
|
18
|
-
|
19
|
-
# define roles, and set configuration variables.
|
10
|
+
class ValidationError < RuntimeError; end
|
11
|
+
|
20
12
|
class Configuration
|
21
|
-
|
22
|
-
|
13
|
+
def self.env
|
14
|
+
@env ||= new
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.reset!
|
18
|
+
@env = new
|
19
|
+
end
|
20
|
+
|
21
|
+
extend Forwardable
|
22
|
+
attr_reader :variables
|
23
|
+
def_delegators :variables,
|
24
|
+
:set, :fetch, :fetch_for, :delete, :keys, :validate
|
25
|
+
|
26
|
+
def initialize(values={})
|
27
|
+
@variables = ValidatedVariables.new(Variables.new(values))
|
28
|
+
end
|
29
|
+
|
30
|
+
def ask(key, default=nil, options={})
|
31
|
+
question = Question.new(key, default, options)
|
32
|
+
set(key, question)
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_if_empty(key, value=nil, &block)
|
36
|
+
set(key, value, &block) unless keys.include?(key)
|
37
|
+
end
|
38
|
+
|
39
|
+
def append(key, *values)
|
40
|
+
set(key, Array(fetch(key)).concat(values))
|
41
|
+
end
|
23
42
|
|
24
|
-
def
|
25
|
-
|
26
|
-
@dry_run = false
|
27
|
-
@preserve_roles = false
|
28
|
-
@logger = Logger.new(options)
|
43
|
+
def remove(key, *values)
|
44
|
+
set(key, Array(fetch(key)) - values)
|
29
45
|
end
|
30
46
|
|
31
|
-
|
32
|
-
|
47
|
+
def any?(key)
|
48
|
+
value = fetch(key)
|
49
|
+
if value && value.respond_to?(:any?)
|
50
|
+
begin
|
51
|
+
return value.any?
|
52
|
+
rescue ArgumentError # rubocop:disable Lint/HandleExceptions
|
53
|
+
# Gracefully ignore values whose `any?` method doesn't accept 0 args
|
54
|
+
end
|
55
|
+
end
|
33
56
|
|
34
|
-
|
35
|
-
|
36
|
-
|
57
|
+
!value.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
def is_question?(key)
|
61
|
+
value = fetch_for(key, nil)
|
62
|
+
!value.nil? && value.is_a?(Question)
|
63
|
+
end
|
64
|
+
|
65
|
+
def role(name, hosts, options={})
|
66
|
+
if name == :all
|
67
|
+
raise ArgumentError, "#{name} reserved name for role. Please choose another name"
|
68
|
+
end
|
69
|
+
|
70
|
+
servers.add_role(name, hosts, options)
|
71
|
+
end
|
72
|
+
|
73
|
+
def server(name, properties={})
|
74
|
+
servers.add_host(name, properties)
|
75
|
+
end
|
76
|
+
|
77
|
+
def roles_for(names)
|
78
|
+
servers.roles_for(names)
|
79
|
+
end
|
80
|
+
|
81
|
+
def role_properties_for(names, &block)
|
82
|
+
servers.role_properties_for(names, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def primary(role)
|
86
|
+
servers.fetch_primary(role)
|
87
|
+
end
|
88
|
+
|
89
|
+
def backend
|
90
|
+
@backend ||= SSHKit
|
91
|
+
end
|
37
92
|
|
38
|
-
|
39
|
-
include Actions::FileTransfer, Actions::Inspect, Actions::Invocation
|
93
|
+
attr_writer :backend
|
40
94
|
|
41
|
-
|
42
|
-
|
95
|
+
def configure_backend
|
96
|
+
backend.configure do |sshkit|
|
97
|
+
configure_sshkit_output(sshkit)
|
98
|
+
sshkit.output_verbosity = fetch(:log_level)
|
99
|
+
sshkit.default_env = fetch(:default_env)
|
100
|
+
sshkit.backend = fetch(:sshkit_backend, SSHKit::Backend::Netssh)
|
101
|
+
sshkit.backend.configure do |backend|
|
102
|
+
backend.pty = fetch(:pty)
|
103
|
+
backend.connection_timeout = fetch(:connection_timeout)
|
104
|
+
backend.ssh_options = (backend.ssh_options || {}).merge(fetch(:ssh_options, {}))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def configure_scm
|
110
|
+
Capistrano::Configuration::SCMResolver.new.resolve
|
111
|
+
end
|
112
|
+
|
113
|
+
def timestamp
|
114
|
+
@timestamp ||= Time.now.utc
|
115
|
+
end
|
116
|
+
|
117
|
+
def add_filter(filter=nil, &block)
|
118
|
+
if block
|
119
|
+
raise ArgumentError, "Both a block and an object were given" if filter
|
120
|
+
|
121
|
+
filter = Object.new
|
122
|
+
def filter.filter(servers)
|
123
|
+
block.call(servers)
|
124
|
+
end
|
125
|
+
elsif !filter.respond_to? :filter
|
126
|
+
raise TypeError, "Provided custom filter <#{filter.inspect}> does " \
|
127
|
+
"not have a public 'filter' method"
|
128
|
+
end
|
129
|
+
@custom_filters ||= []
|
130
|
+
@custom_filters << filter
|
131
|
+
end
|
132
|
+
|
133
|
+
def setup_filters
|
134
|
+
@filters = cmdline_filters
|
135
|
+
@filters += @custom_filters if @custom_filters
|
136
|
+
@filters << Filter.new(:role, ENV["ROLES"]) if ENV["ROLES"]
|
137
|
+
@filters << Filter.new(:host, ENV["HOSTS"]) if ENV["HOSTS"]
|
138
|
+
fh = fetch_for(:filter, {}) || {}
|
139
|
+
@filters << Filter.new(:host, fh[:hosts]) if fh[:hosts]
|
140
|
+
@filters << Filter.new(:role, fh[:roles]) if fh[:roles]
|
141
|
+
@filters << Filter.new(:host, fh[:host]) if fh[:host]
|
142
|
+
@filters << Filter.new(:role, fh[:role]) if fh[:role]
|
143
|
+
end
|
144
|
+
|
145
|
+
def add_cmdline_filter(type, values)
|
146
|
+
cmdline_filters << Filter.new(type, values)
|
147
|
+
end
|
148
|
+
|
149
|
+
def filter(list)
|
150
|
+
setup_filters if @filters.nil?
|
151
|
+
@filters.reduce(list) { |l, f| f.filter l }
|
152
|
+
end
|
153
|
+
|
154
|
+
def dry_run?
|
155
|
+
fetch(:sshkit_backend) == SSHKit::Backend::Printer
|
156
|
+
end
|
157
|
+
|
158
|
+
def install_plugin(plugin, load_hooks: true, load_immediately: false)
|
159
|
+
installer.install(plugin,
|
160
|
+
load_hooks: load_hooks,
|
161
|
+
load_immediately: load_immediately)
|
162
|
+
end
|
163
|
+
|
164
|
+
def scm_plugin_installed?
|
165
|
+
installer.scm_installed?
|
166
|
+
end
|
167
|
+
|
168
|
+
def servers
|
169
|
+
@servers ||= Servers.new
|
170
|
+
end
|
171
|
+
|
172
|
+
private
|
173
|
+
|
174
|
+
def cmdline_filters
|
175
|
+
@cmdline_filters ||= []
|
176
|
+
end
|
177
|
+
|
178
|
+
def installer
|
179
|
+
@installer ||= PluginInstaller.new
|
180
|
+
end
|
181
|
+
|
182
|
+
def configure_sshkit_output(sshkit)
|
183
|
+
format_args = [fetch(:format)]
|
184
|
+
format_args.push(fetch(:format_options)) if any?(:format_options)
|
185
|
+
|
186
|
+
sshkit.use_format(*format_args)
|
187
|
+
end
|
43
188
|
end
|
44
189
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.expand_path("../tasks/console.rake", __FILE__)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
validate :application do |_key, value|
|
2
|
+
changed_value = value.gsub(/[^A-Z0-9\.\-]/i, "_")
|
3
|
+
if value != changed_value
|
4
|
+
warn %Q(The :application value "#{value}" is invalid!)
|
5
|
+
warn "Use only letters, numbers, hyphens, dots, and underscores. For example:"
|
6
|
+
warn " set :application, '#{changed_value}'"
|
7
|
+
raise Capistrano::ValidationError
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
%i(git_strategy hg_strategy svn_strategy).each do |strategy|
|
12
|
+
validate(strategy) do |key, _value|
|
13
|
+
warn(
|
14
|
+
"[Deprecation Warning] #{key} is deprecated and will be removed in "\
|
15
|
+
"Capistrano 3.7.0.\n"\
|
16
|
+
"https://github.com/capistrano/capistrano/blob/master/UPGRADING-3.7.md"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# We use a special :_default_git value so that SCMResolver can tell whether the
|
22
|
+
# default has been replaced by the user via `set`.
|
23
|
+
set_if_empty :scm, Capistrano::Configuration::SCMResolver::DEFAULT_GIT
|
24
|
+
set_if_empty :branch, "master"
|
25
|
+
set_if_empty :deploy_to, -> { "/var/www/#{fetch(:application)}" }
|
26
|
+
set_if_empty :tmp_dir, "/tmp"
|
27
|
+
|
28
|
+
set_if_empty :default_env, {}
|
29
|
+
set_if_empty :keep_releases, 5
|
30
|
+
|
31
|
+
set_if_empty :format, :airbrussh
|
32
|
+
set_if_empty :log_level, :debug
|
33
|
+
|
34
|
+
set_if_empty :pty, false
|
35
|
+
|
36
|
+
set_if_empty :local_user, -> { ENV["USER"] || ENV["LOGNAME"] || ENV["USERNAME"] }
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "capistrano/doctor/output_helpers"
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
module Doctor
|
5
|
+
class EnvironmentDoctor
|
6
|
+
include Capistrano::Doctor::OutputHelpers
|
7
|
+
|
8
|
+
def call
|
9
|
+
title("Environment")
|
10
|
+
puts <<-OUT.gsub(/^\s+/, "")
|
11
|
+
Ruby #{RUBY_DESCRIPTION}
|
12
|
+
Rubygems #{Gem::VERSION}
|
13
|
+
Bundler #{defined?(Bundler::VERSION) ? Bundler::VERSION : 'N/A'}
|
14
|
+
Command #{$PROGRAM_NAME} #{ARGV.join(' ')}
|
15
|
+
OUT
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "capistrano/doctor/output_helpers"
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
module Doctor
|
5
|
+
# Prints table of all Capistrano-related gems and their version numbers. If
|
6
|
+
# there is a newer version of a gem available, call attention to it.
|
7
|
+
class GemsDoctor
|
8
|
+
include Capistrano::Doctor::OutputHelpers
|
9
|
+
|
10
|
+
def call
|
11
|
+
title("Gems")
|
12
|
+
table(all_gem_names) do |gem, row|
|
13
|
+
row.yellow if update_available?(gem)
|
14
|
+
row << gem
|
15
|
+
row << installed_gem_version(gem)
|
16
|
+
row << "(update available)" if update_available?(gem)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def installed_gem_version(gem_name)
|
23
|
+
Gem.loaded_specs[gem_name].version
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_available?(gem_name)
|
27
|
+
latest = Gem.latest_version_for(gem_name)
|
28
|
+
return false if latest.nil?
|
29
|
+
latest > installed_gem_version(gem_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def all_gem_names
|
33
|
+
core_gem_names + plugin_gem_names
|
34
|
+
end
|
35
|
+
|
36
|
+
def core_gem_names
|
37
|
+
%w(capistrano airbrussh rake sshkit net-ssh) & Gem.loaded_specs.keys
|
38
|
+
end
|
39
|
+
|
40
|
+
def plugin_gem_names
|
41
|
+
(Gem.loaded_specs.keys - ["capistrano"]).grep(/capistrano/).sort
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|