capistrano 2.15.11 → 3.0.0.pre
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/.gitignore +17 -8
- data/Gemfile +1 -12
- data/LICENSE.txt +18 -0
- data/README.md +65 -68
- data/Rakefile +4 -10
- data/bin/cap +2 -3
- data/bin/capify +7 -91
- data/capistrano.gemspec +20 -34
- data/lib/Capfile +2 -0
- data/lib/capistrano/application.rb +28 -0
- data/lib/capistrano/bundler.rb +1 -0
- data/lib/capistrano/configuration/question.rb +42 -0
- data/lib/capistrano/configuration/server.rb +24 -0
- data/lib/capistrano/configuration/servers.rb +43 -95
- data/lib/capistrano/configuration.rb +81 -44
- data/lib/capistrano/console.rb +1 -0
- data/lib/capistrano/defaults.rb +11 -0
- data/lib/capistrano/deploy.rb +3 -0
- data/lib/capistrano/dotfile.rb +3 -0
- data/lib/capistrano/dsl/env.rb +57 -0
- data/lib/capistrano/dsl/paths.rb +74 -0
- data/lib/capistrano/dsl/stages.rb +15 -0
- data/lib/capistrano/dsl/task_enhancements.rb +15 -0
- data/lib/capistrano/dsl.rb +38 -0
- data/lib/capistrano/git.rb +1 -0
- data/lib/capistrano/i18n.rb +33 -0
- data/lib/capistrano/install.rb +1 -0
- data/lib/capistrano/setup.rb +17 -0
- data/lib/capistrano/tasks/bundler.rake +13 -0
- data/lib/capistrano/tasks/console.rake +21 -0
- data/lib/capistrano/tasks/deploy.rake +153 -0
- data/lib/capistrano/tasks/framework.rake +45 -0
- data/lib/capistrano/tasks/git.rake +65 -0
- data/lib/capistrano/tasks/install.rake +39 -0
- data/lib/capistrano/templates/Capfile +43 -0
- data/lib/capistrano/templates/deploy.rb.erb +17 -0
- data/lib/capistrano/templates/stage.rb.erb +20 -0
- data/lib/capistrano/version.rb +1 -11
- data/lib/capistrano.rb +9 -3
- data/spec/lib/capistrano/configuration/question_spec.rb +54 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +48 -0
- data/spec/lib/capistrano/configuration/servers_spec.rb +79 -0
- data/spec/lib/capistrano/configuration_spec.rb +80 -0
- data/spec/lib/capistrano/dsl/env_spec.rb +83 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +69 -0
- data/spec/lib/capistrano/dsl_spec.rb +51 -0
- data/spec/lib/capistrano_spec.rb +8 -0
- data/spec/spec_helper.rb +14 -0
- metadata +89 -215
- data/.travis.yml +0 -9
- data/CHANGELOG +0 -1203
- 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 -303
- data/lib/capistrano/configuration/actions/file_transfer.rb +0 -50
- data/lib/capistrano/configuration/actions/inspect.rb +0 -46
- data/lib/capistrano/configuration/actions/invocation.rb +0 -329
- data/lib/capistrano/configuration/alias_task.rb +0 -26
- data/lib/capistrano/configuration/callbacks.rb +0 -147
- data/lib/capistrano/configuration/connections.rb +0 -237
- data/lib/capistrano/configuration/execution.rb +0 -142
- data/lib/capistrano/configuration/loading.rb +0 -205
- data/lib/capistrano/configuration/log_formatters.rb +0 -75
- data/lib/capistrano/configuration/namespaces.rb +0 -223
- data/lib/capistrano/configuration/roles.rb +0 -83
- data/lib/capistrano/configuration/variables.rb +0 -127
- data/lib/capistrano/errors.rb +0 -19
- data/lib/capistrano/ext/multistage.rb +0 -67
- data/lib/capistrano/ext/string.rb +0 -5
- data/lib/capistrano/extensions.rb +0 -57
- data/lib/capistrano/fix_rake_deprecated_dsl.rb +0 -8
- data/lib/capistrano/logger.rb +0 -166
- data/lib/capistrano/processable.rb +0 -55
- data/lib/capistrano/recipes/compat.rb +0 -32
- data/lib/capistrano/recipes/deploy/assets.rb +0 -202
- 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 -117
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
- data/lib/capistrano/recipes/deploy/scm/base.rb +0 -200
- 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 -299
- data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -137
- data/lib/capistrano/recipes/deploy/scm/none.rb +0 -55
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -152
- 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 -92
- data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -338
- 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/unshared_remote_cache.rb +0 -21
- data/lib/capistrano/recipes/deploy/strategy.rb +0 -20
- data/lib/capistrano/recipes/deploy.rb +0 -625
- 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 -265
- data/lib/capistrano/ssh.rb +0 -95
- data/lib/capistrano/task_definition.rb +0 -77
- data/lib/capistrano/transfer.rb +0 -218
- 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 -322
- data/test/configuration/actions/file_transfer_test.rb +0 -61
- data/test/configuration/actions/inspect_test.rb +0 -76
- data/test/configuration/actions/invocation_test.rb +0 -306
- data/test/configuration/alias_task_test.rb +0 -118
- data/test/configuration/callbacks_test.rb +0 -201
- data/test/configuration/connections_test.rb +0 -439
- data/test/configuration/execution_test.rb +0 -175
- data/test/configuration/loading_test.rb +0 -148
- data/test/configuration/namespace_dsl_test.rb +0 -332
- data/test/configuration/roles_test.rb +0 -157
- data/test/configuration/servers_test.rb +0 -183
- data/test/configuration/variables_test.rb +0 -190
- data/test/configuration_test.rb +0 -77
- data/test/deploy/local_dependency_test.rb +0 -76
- data/test/deploy/remote_dependency_test.rb +0 -146
- 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 -274
- data/test/deploy/scm/mercurial_test.rb +0 -134
- data/test/deploy/scm/none_test.rb +0 -35
- data/test/deploy/scm/perforce_test.rb +0 -23
- data/test/deploy/scm/subversion_test.rb +0 -68
- data/test/deploy/strategy/copy_test.rb +0 -360
- 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_formatting_test.rb +0 -149
- data/test/logger_test.rb +0 -134
- 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 -96
- data/test/ssh_test.rb +0 -113
- data/test/task_definition_test.rb +0 -117
- data/test/transfer_test.rb +0 -168
- data/test/utils.rb +0 -37
- data/test/version_test.rb +0 -11
data/lib/capistrano/logger.rb
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
module Capistrano
|
|
2
|
-
class Logger #:nodoc:
|
|
3
|
-
attr_accessor :level, :device, :disable_formatters
|
|
4
|
-
|
|
5
|
-
IMPORTANT = 0
|
|
6
|
-
INFO = 1
|
|
7
|
-
DEBUG = 2
|
|
8
|
-
TRACE = 3
|
|
9
|
-
|
|
10
|
-
MAX_LEVEL = 3
|
|
11
|
-
|
|
12
|
-
COLORS = {
|
|
13
|
-
:none => "0",
|
|
14
|
-
:black => "30",
|
|
15
|
-
:red => "31",
|
|
16
|
-
:green => "32",
|
|
17
|
-
:yellow => "33",
|
|
18
|
-
:blue => "34",
|
|
19
|
-
:magenta => "35",
|
|
20
|
-
:cyan => "36",
|
|
21
|
-
:white => "37"
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
STYLES = {
|
|
25
|
-
:bright => 1,
|
|
26
|
-
:dim => 2,
|
|
27
|
-
:underscore => 4,
|
|
28
|
-
:blink => 5,
|
|
29
|
-
:reverse => 7,
|
|
30
|
-
:hidden => 8
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
# Set up default formatters
|
|
34
|
-
@default_formatters = [
|
|
35
|
-
# TRACE
|
|
36
|
-
{ :match => /command finished/, :color => :white, :style => :dim, :level => 3, :priority => -10 },
|
|
37
|
-
{ :match => /executing locally/, :color => :yellow, :level => 3, :priority => -20 },
|
|
38
|
-
|
|
39
|
-
# DEBUG
|
|
40
|
-
{ :match => /executing `.*/, :color => :green, :level => 2, :priority => -10, :timestamp => true },
|
|
41
|
-
{ :match => /.*/, :color => :yellow, :level => 2, :priority => -30 },
|
|
42
|
-
|
|
43
|
-
# INFO
|
|
44
|
-
{ :match => /.*out\] (fatal:|ERROR:).*/, :color => :red, :level => 1, :priority => -10 },
|
|
45
|
-
{ :match => /Permission denied/, :color => :red, :level => 1, :priority => -20 },
|
|
46
|
-
{ :match => /sh: .+: command not found/, :color => :magenta, :level => 1, :priority => -30 },
|
|
47
|
-
|
|
48
|
-
# IMPORTANT
|
|
49
|
-
{ :match => /^err ::/, :color => :red, :level => 0, :priority => -10 },
|
|
50
|
-
{ :match => /.*/, :color => :blue, :level => 0, :priority => -20 }
|
|
51
|
-
]
|
|
52
|
-
@formatters = @default_formatters
|
|
53
|
-
|
|
54
|
-
class << self
|
|
55
|
-
def default_formatters
|
|
56
|
-
@default_formatters
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def default_formatters=(defaults=nil)
|
|
60
|
-
@default_formatters = [defaults].flatten
|
|
61
|
-
|
|
62
|
-
# reset the formatters
|
|
63
|
-
@formatters = @default_formatters
|
|
64
|
-
@sorted_formatters = nil
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def add_formatter(options) #:nodoc:
|
|
68
|
-
@formatters.push(options)
|
|
69
|
-
@sorted_formatters = nil
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def sorted_formatters
|
|
73
|
-
# Sort matchers in reverse order so we can break if we found a match.
|
|
74
|
-
@sorted_formatters ||= @formatters.sort_by { |i| -(i[:priority] || i[:prio] || 0) }
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def initialize(options={})
|
|
79
|
-
output = options[:output] || $stderr
|
|
80
|
-
if output.respond_to?(:puts)
|
|
81
|
-
@device = output
|
|
82
|
-
else
|
|
83
|
-
@device = File.open(output.to_str, "a")
|
|
84
|
-
@needs_close = true
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
@options = options
|
|
88
|
-
@level = options[:level] || 0
|
|
89
|
-
@disable_formatters = options[:disable_formatters]
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def close
|
|
93
|
-
device.close if @needs_close
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def log(level, message, line_prefix=nil)
|
|
97
|
-
if level <= self.level
|
|
98
|
-
# Only format output if device is a TTY and formatters are not disabled
|
|
99
|
-
if device.tty? && !@disable_formatters
|
|
100
|
-
color = :none
|
|
101
|
-
style = nil
|
|
102
|
-
|
|
103
|
-
Logger.sorted_formatters.each do |formatter|
|
|
104
|
-
if (formatter[:level] == level || formatter[:level].nil?)
|
|
105
|
-
if message =~ formatter[:match] || formatter[:match] =~ line_prefix.to_s
|
|
106
|
-
color = formatter[:color] if formatter[:color]
|
|
107
|
-
style = formatter[:style] || formatter[:attribute] # (support original cap colors)
|
|
108
|
-
message.gsub!(formatter[:match], formatter[:replace]) if formatter[:replace]
|
|
109
|
-
message = formatter[:prepend] + message unless formatter[:prepend].nil?
|
|
110
|
-
message = message + formatter[:append] unless formatter[:append].nil?
|
|
111
|
-
message = Time.now.strftime('%Y-%m-%d %T') + ' ' + message if formatter[:timestamp]
|
|
112
|
-
break unless formatter[:replace]
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
if color == :hide
|
|
118
|
-
# Don't do anything if color is set to :hide
|
|
119
|
-
return false
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
term_color = COLORS[color]
|
|
123
|
-
term_style = STYLES[style]
|
|
124
|
-
|
|
125
|
-
# Don't format message if no color or style
|
|
126
|
-
unless color == :none and style.nil?
|
|
127
|
-
unless line_prefix.nil?
|
|
128
|
-
line_prefix = format(line_prefix, term_color, term_style, nil)
|
|
129
|
-
end
|
|
130
|
-
message = format(message, term_color, term_style)
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
indent = "%*s" % [MAX_LEVEL, "*" * (MAX_LEVEL - level)]
|
|
135
|
-
(RUBY_VERSION >= "1.9" ? message.lines : message).each do |line|
|
|
136
|
-
if line_prefix
|
|
137
|
-
device.puts "#{indent} [#{line_prefix}] #{line.strip}\n"
|
|
138
|
-
else
|
|
139
|
-
device.puts "#{indent} #{line.strip}\n"
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def important(message, line_prefix=nil)
|
|
146
|
-
log(IMPORTANT, message, line_prefix)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def info(message, line_prefix=nil)
|
|
150
|
-
log(INFO, message, line_prefix)
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def debug(message, line_prefix=nil)
|
|
154
|
-
log(DEBUG, message, line_prefix)
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def trace(message, line_prefix=nil)
|
|
158
|
-
log(TRACE, message, line_prefix)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def format(message, color, style, nl = "\n")
|
|
162
|
-
style = "#{style};" if style
|
|
163
|
-
"\e[#{style}#{color}m" + message.to_s.strip + "\e[0m#{nl}"
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
module Capistrano
|
|
2
|
-
module Processable
|
|
3
|
-
module SessionAssociation
|
|
4
|
-
def self.on(exception, session)
|
|
5
|
-
unless exception.respond_to?(:session)
|
|
6
|
-
exception.extend(self)
|
|
7
|
-
exception.session = session
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
return exception
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
attr_accessor :session
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def process_iteration(wait=nil, &block)
|
|
17
|
-
ensure_each_session { |session| session.preprocess }
|
|
18
|
-
|
|
19
|
-
return false if block && !block.call(self)
|
|
20
|
-
|
|
21
|
-
readers = sessions.map { |session| session.listeners.keys }.flatten.reject { |io| io.closed? }
|
|
22
|
-
writers = readers.select { |io| io.respond_to?(:pending_write?) && io.pending_write? }
|
|
23
|
-
|
|
24
|
-
if readers.any? || writers.any?
|
|
25
|
-
readers, writers, = IO.select(readers, writers, nil, wait)
|
|
26
|
-
else
|
|
27
|
-
return false
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
if readers
|
|
31
|
-
ensure_each_session do |session|
|
|
32
|
-
ios = session.listeners.keys
|
|
33
|
-
session.postprocess(ios & readers, ios & writers)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
true
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def ensure_each_session
|
|
41
|
-
errors = []
|
|
42
|
-
|
|
43
|
-
sessions.each do |session|
|
|
44
|
-
begin
|
|
45
|
-
yield session
|
|
46
|
-
rescue Exception => error
|
|
47
|
-
errors << SessionAssociation.on(error, session)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
raise errors.first if errors.any?
|
|
52
|
-
sessions
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# A collection of compatibility scripts, to ease the transition between
|
|
2
|
-
# Capistrano 1.x and Capistrano 2.x.
|
|
3
|
-
|
|
4
|
-
# Depends on the deployment system
|
|
5
|
-
load 'deploy'
|
|
6
|
-
|
|
7
|
-
map = { "diff_from_last_deploy" => "deploy:pending:diff",
|
|
8
|
-
"update" => "deploy:update",
|
|
9
|
-
"update_code" => "deploy:update_code",
|
|
10
|
-
"symlink" => "deploy:create_symlink",
|
|
11
|
-
"restart" => "deploy:restart",
|
|
12
|
-
"rollback" => "deploy:rollback",
|
|
13
|
-
"cleanup" => "deploy:cleanup",
|
|
14
|
-
"disable_web" => "deploy:web:disable",
|
|
15
|
-
"enable_web" => "deploy:web:enable",
|
|
16
|
-
"cold_deploy" => "deploy:cold",
|
|
17
|
-
"deploy_with_migrations" => "deploy:migrations" }
|
|
18
|
-
|
|
19
|
-
map.each do |old, new|
|
|
20
|
-
desc "DEPRECATED: See #{new}."
|
|
21
|
-
eval "task(#{old.inspect}) do
|
|
22
|
-
warn \"[DEPRECATED] `#{old}' is deprecated. Use `#{new}' instead.\"
|
|
23
|
-
find_and_execute_task(#{new.inspect})
|
|
24
|
-
end"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
desc "DEPRECATED: See deploy:start."
|
|
28
|
-
task :spinner do
|
|
29
|
-
warn "[DEPRECATED] `spinner' is deprecated. Use `deploy:start' instead."
|
|
30
|
-
set :runner, fetch(:spinner_user, "app")
|
|
31
|
-
deploy.start
|
|
32
|
-
end
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
require 'json'
|
|
2
|
-
|
|
3
|
-
load 'deploy' unless defined?(_cset)
|
|
4
|
-
|
|
5
|
-
_cset :asset_env, "RAILS_GROUPS=assets"
|
|
6
|
-
_cset :assets_prefix, "assets"
|
|
7
|
-
_cset :shared_assets_prefix, "assets"
|
|
8
|
-
_cset :assets_role, [:web]
|
|
9
|
-
_cset :expire_assets_after, (3600 * 24 * 7)
|
|
10
|
-
_cset(:asset_manifest_prefix) { (`sprockets -v`.chomp < "3.0" ? "manifest" : ".sprockets-manifest") rescue "manifest" }
|
|
11
|
-
|
|
12
|
-
_cset :normalize_asset_timestamps, false
|
|
13
|
-
|
|
14
|
-
before 'deploy:finalize_update', 'deploy:assets:symlink'
|
|
15
|
-
after 'deploy:update_code', 'deploy:assets:precompile'
|
|
16
|
-
before 'deploy:assets:precompile', 'deploy:assets:update_asset_mtimes'
|
|
17
|
-
after 'deploy:cleanup', 'deploy:assets:clean_expired'
|
|
18
|
-
after 'deploy:rollback:revision', 'deploy:assets:rollback'
|
|
19
|
-
|
|
20
|
-
def shared_manifest_path
|
|
21
|
-
@shared_manifest_path ||= capture("ls #{shared_path.shellescape}/#{shared_assets_prefix}/#{asset_manifest_prefix}*").strip
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Parses manifest and returns array of uncompressed and compressed asset filenames with and without digests
|
|
25
|
-
# "Intelligently" determines format of string - supports YAML and JSON
|
|
26
|
-
def parse_manifest(str)
|
|
27
|
-
assets_hash = str[0,1] == '{' ? JSON.parse(str)['assets'] : YAML.load(str)
|
|
28
|
-
|
|
29
|
-
assets_hash.to_a.flatten.map {|a| [a, "#{a}.gz"] }.flatten
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
namespace :deploy do
|
|
33
|
-
namespace :assets do
|
|
34
|
-
desc <<-DESC
|
|
35
|
-
[internal] This task will set up a symlink to the shared directory \
|
|
36
|
-
for the assets directory. Assets are shared across deploys to avoid \
|
|
37
|
-
mid-deploy mismatches between old application html asking for assets \
|
|
38
|
-
and getting a 404 file not found error. The assets cache is shared \
|
|
39
|
-
for efficiency. If you customize the assets path prefix, override the \
|
|
40
|
-
:assets_prefix variable to match. If you customize shared assets path \
|
|
41
|
-
prefix, override :shared_assets_prefix variable to match.
|
|
42
|
-
DESC
|
|
43
|
-
task :symlink, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
|
44
|
-
run <<-CMD.compact
|
|
45
|
-
rm -rf #{latest_release}/public/#{assets_prefix} &&
|
|
46
|
-
mkdir -p #{latest_release}/public &&
|
|
47
|
-
mkdir -p #{shared_path}/#{shared_assets_prefix} &&
|
|
48
|
-
ln -s #{shared_path}/#{shared_assets_prefix} #{latest_release}/public/#{assets_prefix}
|
|
49
|
-
CMD
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
desc <<-DESC
|
|
53
|
-
Run the asset precompilation rake task. You can specify the full path \
|
|
54
|
-
to the rake executable by setting the rake variable. You can also \
|
|
55
|
-
specify additional environment variables to pass to rake via the \
|
|
56
|
-
asset_env variable. The defaults are:
|
|
57
|
-
|
|
58
|
-
set :rake, "rake"
|
|
59
|
-
set :rails_env, "production"
|
|
60
|
-
set :asset_env, "RAILS_GROUPS=assets"
|
|
61
|
-
DESC
|
|
62
|
-
task :precompile, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
|
63
|
-
run <<-CMD.compact
|
|
64
|
-
cd -- #{latest_release} &&
|
|
65
|
-
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
|
66
|
-
CMD
|
|
67
|
-
|
|
68
|
-
if capture("ls -1 #{shared_path.shellescape}/#{shared_assets_prefix}/#{asset_manifest_prefix}* | wc -l").to_i > 1
|
|
69
|
-
raise "More than one asset manifest file was found in '#{shared_path.shellescape}/#{shared_assets_prefix}'. If you are upgrading a Rails 3 application to Rails 4, follow these instructions: http://github.com/capistrano/capistrano/wiki/Upgrading-to-Rails-4#asset-pipeline"
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Sync manifest filenames across servers if our manifest has a random filename
|
|
73
|
-
if shared_manifest_path =~ /#{asset_manifest_prefix}-.+\./
|
|
74
|
-
run <<-CMD.compact
|
|
75
|
-
[ -e #{shared_manifest_path.shellescape} ] || mv -- #{shared_path.shellescape}/#{shared_assets_prefix}/#{asset_manifest_prefix}* #{shared_manifest_path.shellescape}
|
|
76
|
-
CMD
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Copy manifest to release root (for clean_expired task)
|
|
80
|
-
run <<-CMD.compact
|
|
81
|
-
cp -- #{shared_manifest_path.shellescape} #{current_release.to_s.shellescape}/assets_manifest#{File.extname(shared_manifest_path)}
|
|
82
|
-
CMD
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
desc <<-DESC
|
|
86
|
-
[internal] Updates the mtimes for assets that are required by the current release.
|
|
87
|
-
This task runs before assets:precompile.
|
|
88
|
-
DESC
|
|
89
|
-
task :update_asset_mtimes, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
|
90
|
-
# Fetch assets/manifest contents.
|
|
91
|
-
manifest_content = capture("[ -e '#{shared_path.shellescape}/#{shared_assets_prefix}/#{asset_manifest_prefix}*' ] && cat #{shared_path.shellescape}/#{shared_assets_prefix}/#{asset_manifest_prefix}* || echo").strip
|
|
92
|
-
|
|
93
|
-
if manifest_content != ""
|
|
94
|
-
current_assets = parse_manifest(manifest_content)
|
|
95
|
-
logger.info "Updating mtimes for ~#{current_assets.count} assets..."
|
|
96
|
-
put current_assets.map{|a| "#{shared_path}/#{shared_assets_prefix}/#{a}" }.join("\n"), "#{deploy_to}/TOUCH_ASSETS", :via => :scp
|
|
97
|
-
run <<-CMD.compact
|
|
98
|
-
cat #{deploy_to.shellescape}/TOUCH_ASSETS | while read asset; do
|
|
99
|
-
touch -c -- "$asset";
|
|
100
|
-
done &&
|
|
101
|
-
rm -f -- #{deploy_to.shellescape}/TOUCH_ASSETS
|
|
102
|
-
CMD
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
desc <<-DESC
|
|
107
|
-
Run the asset clean rake task. Use with caution, this will delete \
|
|
108
|
-
all of your compiled assets. You can specify the full path \
|
|
109
|
-
to the rake executable by setting the rake variable. You can also \
|
|
110
|
-
specify additional environment variables to pass to rake via the \
|
|
111
|
-
asset_env variable. The defaults are:
|
|
112
|
-
|
|
113
|
-
set :rake, "rake"
|
|
114
|
-
set :rails_env, "production"
|
|
115
|
-
set :asset_env, "RAILS_GROUPS=assets"
|
|
116
|
-
DESC
|
|
117
|
-
task :clean, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
|
118
|
-
run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:clean"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
desc <<-DESC
|
|
122
|
-
Clean up any assets that haven't been deployed for more than :expire_assets_after seconds.
|
|
123
|
-
Default time to keep old assets is one week. Set the :expire_assets_after variable
|
|
124
|
-
to change the assets expiry time. Assets will only be deleted if they are not required by
|
|
125
|
-
an existing release.
|
|
126
|
-
DESC
|
|
127
|
-
task :clean_expired, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
|
128
|
-
# Fetch all assets_manifest contents.
|
|
129
|
-
manifests_output = capture <<-CMD.compact
|
|
130
|
-
for manifest in #{releases_path.shellescape}/*/assets_manifest.*; do
|
|
131
|
-
cat -- "$manifest" 2> /dev/null && printf ':::' || true;
|
|
132
|
-
done
|
|
133
|
-
CMD
|
|
134
|
-
manifests = manifests_output.split(':::')
|
|
135
|
-
|
|
136
|
-
if manifests.empty?
|
|
137
|
-
logger.info "No manifests in #{releases_path}/*/assets_manifest.*"
|
|
138
|
-
else
|
|
139
|
-
logger.info "Fetched #{manifests.count} manifests from #{releases_path}/*/assets_manifest.*"
|
|
140
|
-
current_assets = Set.new
|
|
141
|
-
manifests.each do |content|
|
|
142
|
-
current_assets += parse_manifest(content)
|
|
143
|
-
end
|
|
144
|
-
current_assets += [File.basename(shared_manifest_path), "sources_manifest.yml"]
|
|
145
|
-
|
|
146
|
-
# Write the list of required assets to server.
|
|
147
|
-
logger.info "Writing required assets to #{deploy_to}/REQUIRED_ASSETS..."
|
|
148
|
-
escaped_assets = current_assets.sort.join("\n").gsub("\"", "\\\"") << "\n"
|
|
149
|
-
put escaped_assets, "#{deploy_to}/REQUIRED_ASSETS", :via => :scp
|
|
150
|
-
|
|
151
|
-
# Finds all files older than X minutes, then removes them if they are not referenced
|
|
152
|
-
# in REQUIRED_ASSETS.
|
|
153
|
-
expire_after_mins = (expire_assets_after.to_f / 60.0).to_i
|
|
154
|
-
logger.info "Removing assets that haven't been deployed for #{expire_after_mins} minutes..."
|
|
155
|
-
# LC_COLLATE=C tells the `sort` and `comm` commands to sort files in byte order.
|
|
156
|
-
run <<-CMD.compact
|
|
157
|
-
cd -- #{deploy_to.shellescape}/ &&
|
|
158
|
-
LC_COLLATE=C sort REQUIRED_ASSETS -o REQUIRED_ASSETS &&
|
|
159
|
-
cd -- #{shared_path.shellescape}/#{shared_assets_prefix}/ &&
|
|
160
|
-
for f in $(
|
|
161
|
-
find * -mmin +#{expire_after_mins.to_s.shellescape} -type f | LC_COLLATE=C sort |
|
|
162
|
-
LC_COLLATE=C comm -23 -- - #{deploy_to.shellescape}/REQUIRED_ASSETS
|
|
163
|
-
); do
|
|
164
|
-
echo "Removing unneeded asset: $f";
|
|
165
|
-
rm -f -- "$f";
|
|
166
|
-
done;
|
|
167
|
-
rm -f -- #{deploy_to.shellescape}/REQUIRED_ASSETS
|
|
168
|
-
CMD
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
desc <<-DESC
|
|
173
|
-
Rolls back assets to the previous release by symlinking the release's manifest
|
|
174
|
-
to shared/assets/manifest, and finally recompiling or regenerating nondigest assets.
|
|
175
|
-
DESC
|
|
176
|
-
task :rollback, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
|
177
|
-
previous_manifest = capture("ls #{previous_release.shellescape}/assets_manifest.*").strip
|
|
178
|
-
if capture("[ -e #{previous_manifest.shellescape} ] && echo true || echo false").strip != 'true'
|
|
179
|
-
puts "#{previous_manifest} is missing! Cannot roll back assets. " <<
|
|
180
|
-
"Please run deploy:assets:precompile to update your assets when the rollback is finished."
|
|
181
|
-
else
|
|
182
|
-
# If the user is rolling back a Rails 4 app to Rails 3
|
|
183
|
-
if File.extname(previous_manifest) == '.yml' && File.extname(shared_manifest_path) == '.json'
|
|
184
|
-
# Remove the existing JSON manifest
|
|
185
|
-
run "rm -f -- #{shared_manifest_path.shellescape}"
|
|
186
|
-
|
|
187
|
-
# Restore the manifest to the Rails 3 path
|
|
188
|
-
restored_manifest_path = "#{shared_path.shellescape}/#{shared_assets_prefix}/manifest.yml"
|
|
189
|
-
else
|
|
190
|
-
# If the user is not rolling back from Rails 4 to 3, we just want to replace the current manifest
|
|
191
|
-
restored_manifest_path = shared_manifest_path
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
run <<-CMD.compact
|
|
195
|
-
cd -- #{previous_release.shellescape} &&
|
|
196
|
-
cp -f -- #{previous_manifest.shellescape} #{restored_manifest_path.shellescape} &&
|
|
197
|
-
[ -z "$(#{rake} -P | grep assets:precompile:nondigest)" ] || #{rake} RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} assets:precompile:nondigest
|
|
198
|
-
CMD
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
require 'capistrano/recipes/deploy/local_dependency'
|
|
2
|
-
require 'capistrano/recipes/deploy/remote_dependency'
|
|
3
|
-
|
|
4
|
-
module Capistrano
|
|
5
|
-
module Deploy
|
|
6
|
-
class Dependencies
|
|
7
|
-
include Enumerable
|
|
8
|
-
|
|
9
|
-
attr_reader :configuration
|
|
10
|
-
|
|
11
|
-
def initialize(configuration)
|
|
12
|
-
@configuration = configuration
|
|
13
|
-
@dependencies = []
|
|
14
|
-
yield self if block_given?
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def check
|
|
18
|
-
yield self
|
|
19
|
-
self
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def remote
|
|
23
|
-
dep = RemoteDependency.new(configuration)
|
|
24
|
-
@dependencies << dep
|
|
25
|
-
dep
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def local
|
|
29
|
-
dep = LocalDependency.new(configuration)
|
|
30
|
-
@dependencies << dep
|
|
31
|
-
dep
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def each
|
|
35
|
-
@dependencies.each { |d| yield d }
|
|
36
|
-
self
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def pass?
|
|
40
|
-
all? { |d| d.pass? }
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
module Capistrano
|
|
2
|
-
module Deploy
|
|
3
|
-
class LocalDependency
|
|
4
|
-
attr_reader :configuration
|
|
5
|
-
attr_reader :message
|
|
6
|
-
|
|
7
|
-
def initialize(configuration)
|
|
8
|
-
@configuration = configuration
|
|
9
|
-
@success = true
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def command(command)
|
|
13
|
-
@message ||= "`#{command}' could not be found in the path on the local host"
|
|
14
|
-
@success = find_in_path(command)
|
|
15
|
-
self
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def or(message)
|
|
19
|
-
@message = message
|
|
20
|
-
self
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def pass?
|
|
24
|
-
@success
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
# Searches the path, looking for the given utility. If an executable
|
|
30
|
-
# file is found that matches the parameter, this returns true.
|
|
31
|
-
def find_in_path(utility)
|
|
32
|
-
path = (ENV['PATH'] || "").split(File::PATH_SEPARATOR)
|
|
33
|
-
suffixes = self.class.on_windows? ? self.class.windows_executable_extensions : [""]
|
|
34
|
-
|
|
35
|
-
path.each do |dir|
|
|
36
|
-
suffixes.each do |sfx|
|
|
37
|
-
file = File.join(dir, utility + sfx)
|
|
38
|
-
return true if File.executable?(file)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
false
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def self.on_windows?
|
|
46
|
-
RUBY_PLATFORM =~ /mswin|mingw/
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def self.windows_executable_extensions
|
|
50
|
-
%w(.exe .bat .com .cmd)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
require 'capistrano/errors'
|
|
2
|
-
|
|
3
|
-
module Capistrano
|
|
4
|
-
module Deploy
|
|
5
|
-
class RemoteDependency
|
|
6
|
-
attr_reader :configuration
|
|
7
|
-
attr_reader :hosts
|
|
8
|
-
|
|
9
|
-
def initialize(configuration)
|
|
10
|
-
@configuration = configuration
|
|
11
|
-
@success = true
|
|
12
|
-
@hosts = nil
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def directory(path, options={})
|
|
16
|
-
@message ||= "`#{path}' is not a directory"
|
|
17
|
-
try("test -d #{path}", options)
|
|
18
|
-
self
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def file(path, options={})
|
|
22
|
-
@message ||= "`#{path}' is not a file"
|
|
23
|
-
try("test -f #{path}", options)
|
|
24
|
-
self
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def writable(path, options={})
|
|
28
|
-
@message ||= "`#{path}' is not writable"
|
|
29
|
-
try("test -w #{path}", options)
|
|
30
|
-
self
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def command(command, options={})
|
|
34
|
-
@message ||= "`#{command}' could not be found in the path"
|
|
35
|
-
try("which #{command}", options)
|
|
36
|
-
self
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def gem(name, version, options={})
|
|
40
|
-
@message ||= "gem `#{name}' #{version} could not be found"
|
|
41
|
-
gem_cmd = configuration.fetch(:gem_command, "gem")
|
|
42
|
-
try("#{gem_cmd} specification --version '#{version}' #{name} 2>&1 | awk 'BEGIN { s = 0 } /^name:/ { s = 1; exit }; END { if(s == 0) exit 1 }'", options)
|
|
43
|
-
self
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def deb(name, version, options={})
|
|
47
|
-
@message ||= "package `#{name}' #{version} could not be found"
|
|
48
|
-
try("dpkg -s #{name} | grep '^Version: #{version}'", options)
|
|
49
|
-
self
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def rpm(name, version, options={})
|
|
53
|
-
@message ||= "package `#{name}' #{version} could not be found"
|
|
54
|
-
try("rpm -q #{name} | grep '#{version}'", options)
|
|
55
|
-
self
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def match(command, expect, options={})
|
|
59
|
-
expect = Regexp.new(Regexp.escape(expect.to_s)) unless expect.is_a?(Regexp)
|
|
60
|
-
|
|
61
|
-
output_per_server = {}
|
|
62
|
-
try("#{command} ", options) do |ch, stream, out|
|
|
63
|
-
output_per_server[ch[:server]] ||= ''
|
|
64
|
-
output_per_server[ch[:server]] += out
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# It is possible for some of these commands to return a status != 0
|
|
68
|
-
# (for example, rake --version exits with a 1). For this check we
|
|
69
|
-
# just care if the output matches, so we reset the success flag.
|
|
70
|
-
@success = true
|
|
71
|
-
|
|
72
|
-
errored_hosts = []
|
|
73
|
-
output_per_server.each_pair do |server, output|
|
|
74
|
-
next if output =~ expect
|
|
75
|
-
errored_hosts << server
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
if errored_hosts.any?
|
|
79
|
-
@hosts = errored_hosts.join(', ')
|
|
80
|
-
output = output_per_server[errored_hosts.first]
|
|
81
|
-
@message = "the output #{output.inspect} from #{command.inspect} did not match #{expect.inspect}"
|
|
82
|
-
@success = false
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
self
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def or(message)
|
|
89
|
-
@message = message
|
|
90
|
-
self
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def pass?
|
|
94
|
-
@success
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def message
|
|
98
|
-
s = @message.dup
|
|
99
|
-
s << " (#{@hosts})" if @hosts
|
|
100
|
-
s
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
private
|
|
104
|
-
|
|
105
|
-
def try(command, options)
|
|
106
|
-
return unless @success # short-circuit evaluation
|
|
107
|
-
configuration.invoke_command(command, options) do |ch,stream,out|
|
|
108
|
-
warn "#{ch[:server]}: #{out}" if stream == :err
|
|
109
|
-
yield ch, stream, out if block_given?
|
|
110
|
-
end
|
|
111
|
-
rescue Capistrano::CommandError => e
|
|
112
|
-
@success = false
|
|
113
|
-
@hosts = e.hosts.join(', ')
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|