capistrano 2.13.5 → 2.14.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -1
- data/lib/capistrano/cli/help.rb +1 -1
- data/lib/capistrano/configuration.rb +8 -1
- data/lib/capistrano/configuration/actions/invocation.rb +1 -1
- data/lib/capistrano/configuration/namespaces.rb +1 -1
- data/lib/capistrano/recipes/deploy.rb +8 -6
- data/lib/capistrano/recipes/deploy/assets.rb +106 -4
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +9 -4
- data/lib/capistrano/version.rb +2 -2
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
## 2.
|
1
|
+
## 2.14.1 (tentative) / January 10 2013
|
2
2
|
|
3
|
+
## 2.14.0 / January 9 2013
|
4
|
+
|
5
|
+
* Removed ui.output_cols limit of 80 chars (@aussielunix)
|
6
|
+
* Added :p4charset variable for Perforce command line (@randyinla)
|
7
|
+
* Added support for rolling back assets, and removing expired assets (@ndbroadbent)
|
3
8
|
* Merged in `capistrano_colors` gem, and renamed to 'log_formatters', since it does much more than just colors
|
4
9
|
(@ndbroadbent)
|
5
10
|
* Use more intelligence in setting the :scm variable based on known version control directory names (@czarneckid)
|
data/lib/capistrano/cli/help.rb
CHANGED
@@ -112,7 +112,7 @@ module Capistrano
|
|
112
112
|
|
113
113
|
def output_columns #:nodoc:
|
114
114
|
if ( @output_columns.nil? )
|
115
|
-
if ( self.class.ui.output_cols.nil?
|
115
|
+
if ( self.class.ui.output_cols.nil? )
|
116
116
|
@output_columns = 80
|
117
117
|
else
|
118
118
|
@output_columns = self.class.ui.output_cols
|
@@ -43,7 +43,14 @@ module Capistrano
|
|
43
43
|
# Must mix last, because it hooks into previously defined methods
|
44
44
|
include Callbacks
|
45
45
|
|
46
|
-
(
|
46
|
+
(self.instance_methods & Kernel.methods).select do |name|
|
47
|
+
# Select the instance methods owned by the Configuration class.
|
48
|
+
self.instance_method(name).owner.to_s.start_with?("Capistrano::Configuration")
|
49
|
+
end.select do |name|
|
50
|
+
# Of those, select methods that are being shadowed by the Kernel module in the Namespace class.
|
51
|
+
Namespaces::Namespace.method_defined?(name) && Namespaces::Namespace.instance_method(name).owner == Kernel
|
52
|
+
end.each do |name|
|
53
|
+
# Undefine the shadowed methods, since we want Namespace objects to defer handling to the Configuration object.
|
47
54
|
Namespaces::Namespace.send(:undef_method, name)
|
48
55
|
end
|
49
56
|
end
|
@@ -160,7 +160,7 @@ module Capistrano
|
|
160
160
|
# or #invoke_command.
|
161
161
|
def run_tree(tree, options={}) #:nodoc:
|
162
162
|
if tree.branches.empty? && tree.fallback
|
163
|
-
logger.debug "executing #{tree.fallback}"
|
163
|
+
logger.debug "executing #{tree.fallback}" unless options[:silent]
|
164
164
|
elsif tree.branches.any?
|
165
165
|
logger.debug "executing multiple commands in parallel"
|
166
166
|
tree.each do |branch|
|
@@ -213,7 +213,7 @@ module Kernel
|
|
213
213
|
|
214
214
|
namespace = Capistrano::Configuration::Namespaces::Namespace
|
215
215
|
|
216
|
-
if namespace.method_defined?(name) && namespace.
|
216
|
+
if namespace.method_defined?(name) && namespace.instance_method(name).owner == Kernel
|
217
217
|
namespace.send :undef_method, name
|
218
218
|
end
|
219
219
|
|
@@ -1,8 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "benchmark"
|
2
|
+
require "set"
|
3
|
+
require "shellwords"
|
4
|
+
require "yaml"
|
5
|
+
require "capistrano/recipes/deploy/scm"
|
6
|
+
require "capistrano/recipes/deploy/strategy"
|
6
7
|
|
7
8
|
def _cset(name, *args, &block)
|
8
9
|
unless exists?(name)
|
@@ -287,7 +288,8 @@ namespace :deploy do
|
|
287
288
|
if fetch(:normalize_asset_timestamps, true)
|
288
289
|
stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
|
289
290
|
asset_paths = fetch(:public_children, %w(images stylesheets javascripts)).map { |p| "#{escaped_release}/public/#{p}" }
|
290
|
-
run("find #{asset_paths.join(" ")
|
291
|
+
run("find #{asset_paths.join(" ")} -exec touch -t #{stamp} -- {} ';'; true",
|
292
|
+
:env => { "TZ" => "UTC" }) if asset_paths.any?
|
291
293
|
end
|
292
294
|
end
|
293
295
|
|
@@ -3,11 +3,15 @@ load 'deploy' unless defined?(_cset)
|
|
3
3
|
_cset :asset_env, "RAILS_GROUPS=assets"
|
4
4
|
_cset :assets_prefix, "assets"
|
5
5
|
_cset :assets_role, [:web]
|
6
|
+
_cset :expire_assets_after, (3600 * 24 * 7)
|
6
7
|
|
7
8
|
_cset :normalize_asset_timestamps, false
|
8
9
|
|
9
|
-
before 'deploy:finalize_update',
|
10
|
-
after
|
10
|
+
before 'deploy:finalize_update', 'deploy:assets:symlink'
|
11
|
+
after 'deploy:update_code', 'deploy:assets:precompile'
|
12
|
+
before 'deploy:assets:precompile', 'deploy:assets:update_asset_mtimes'
|
13
|
+
after 'deploy:cleanup', 'deploy:assets:clean_expired'
|
14
|
+
after 'deploy:rollback:revision', 'deploy:assets:rollback'
|
11
15
|
|
12
16
|
namespace :deploy do
|
13
17
|
namespace :assets do
|
@@ -20,7 +24,7 @@ namespace :deploy do
|
|
20
24
|
:assets_prefix variable to match.
|
21
25
|
DESC
|
22
26
|
task :symlink, :roles => assets_role, :except => { :no_release => true } do
|
23
|
-
run <<-CMD
|
27
|
+
run <<-CMD.compact
|
24
28
|
rm -rf #{latest_release}/public/#{assets_prefix} &&
|
25
29
|
mkdir -p #{latest_release}/public &&
|
26
30
|
mkdir -p #{shared_path}/assets &&
|
@@ -39,7 +43,34 @@ namespace :deploy do
|
|
39
43
|
set :asset_env, "RAILS_GROUPS=assets"
|
40
44
|
DESC
|
41
45
|
task :precompile, :roles => assets_role, :except => { :no_release => true } do
|
42
|
-
run
|
46
|
+
run <<-CMD.compact
|
47
|
+
cd -- #{latest_release.shellescape} &&
|
48
|
+
#{rake} RAILS_ENV=#{rails_env.shellescape} #{asset_env} assets:precompile &&
|
49
|
+
cp -- #{shared_path.shellescape}/assets/manifest.yml #{current_release.shellescape}/assets_manifest.yml
|
50
|
+
CMD
|
51
|
+
end
|
52
|
+
|
53
|
+
desc <<-DESC
|
54
|
+
[internal] Updates the mtimes for assets that are required by the current release.
|
55
|
+
This task runs before assets:precompile.
|
56
|
+
DESC
|
57
|
+
task :update_asset_mtimes, :roles => assets_role, :except => { :no_release => true } do
|
58
|
+
# Fetch assets/manifest.yml contents.
|
59
|
+
manifest_path = "#{shared_path}/assets/manifest.yml"
|
60
|
+
manifest_yml = capture("[ -e #{manifest_path.shellescape} ] && cat #{manifest_path.shellescape} || echo").strip
|
61
|
+
|
62
|
+
if manifest_yml != ""
|
63
|
+
manifest = YAML.load(manifest_yml)
|
64
|
+
current_assets = manifest.to_a.flatten.map {|a| [a, "#{a}.gz"] }.flatten
|
65
|
+
logger.info "Updating mtimes for ~#{current_assets.count} assets..."
|
66
|
+
put current_assets.map{|a| "#{shared_path}/assets/#{a}" }.join("\n"), "#{deploy_to}/TOUCH_ASSETS"
|
67
|
+
run <<-CMD.compact
|
68
|
+
cat #{deploy_to.shellescape}/TOUCH_ASSETS | while read asset; do
|
69
|
+
touch -cm -- "$asset";
|
70
|
+
done &&
|
71
|
+
rm -f -- #{deploy_to.shellescape}/TOUCH_ASSETS
|
72
|
+
CMD
|
73
|
+
end
|
43
74
|
end
|
44
75
|
|
45
76
|
desc <<-DESC
|
@@ -56,5 +87,76 @@ namespace :deploy do
|
|
56
87
|
task :clean, :roles => assets_role, :except => { :no_release => true } do
|
57
88
|
run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:clean"
|
58
89
|
end
|
90
|
+
|
91
|
+
desc <<-DESC
|
92
|
+
Clean up any assets that haven't been deployed for more than :expire_assets_after seconds.
|
93
|
+
Default time to keep old assets is one week. Set the :expire_assets_after variable
|
94
|
+
to change the assets expiry time. Assets will only be deleted if they are not required by
|
95
|
+
an existing release.
|
96
|
+
DESC
|
97
|
+
task :clean_expired, :roles => assets_role, :except => { :no_release => true } do
|
98
|
+
# Fetch all assets_manifest.yml contents.
|
99
|
+
manifests_output = capture <<-CMD.compact
|
100
|
+
for manifest in #{releases_path.shellescape}/*/assets_manifest.yml; do
|
101
|
+
cat -- "$manifest" 2> /dev/null && printf ':::' || true;
|
102
|
+
done
|
103
|
+
CMD
|
104
|
+
manifests = manifests_output.split(':::')
|
105
|
+
|
106
|
+
if manifests.empty?
|
107
|
+
logger.info "No manifests in #{releases_path}/*/assets_manifest.yml"
|
108
|
+
else
|
109
|
+
logger.info "Fetched #{manifests.count} manifests from #{releases_path}/*/assets_manifest.yml"
|
110
|
+
current_assets = Set.new
|
111
|
+
manifests.each do |yaml|
|
112
|
+
manifest = YAML.load(yaml)
|
113
|
+
current_assets += manifest.to_a.flatten.flat_map do |file|
|
114
|
+
[file, "#{file}.gz"]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
current_assets += %w(manifest.yml sources_manifest.yml)
|
118
|
+
|
119
|
+
# Write the list of required assets to server.
|
120
|
+
logger.info "Writing required assets to #{deploy_to}/REQUIRED_ASSETS..."
|
121
|
+
escaped_assets = current_assets.sort.join("\n").gsub("\"", "\\\"") << "\n"
|
122
|
+
put escaped_assets, "#{deploy_to}/REQUIRED_ASSETS"
|
123
|
+
|
124
|
+
# Finds all files older than X minutes, then removes them if they are not referenced
|
125
|
+
# in REQUIRED_ASSETS.
|
126
|
+
expire_after_mins = (expire_assets_after.to_f / 60.0).to_i
|
127
|
+
logger.info "Removing assets that haven't been deployed for #{expire_after_mins} minutes..."
|
128
|
+
# LC_COLLATE=C tells the `sort` and `comm` commands to sort files in byte order.
|
129
|
+
run <<-CMD.compact
|
130
|
+
cd -- #{shared_path.shellescape}/assets/ &&
|
131
|
+
for f in $(
|
132
|
+
find * -mmin +#{expire_after_mins.to_s.shellescape} -type f | LC_COLLATE=C sort |
|
133
|
+
LC_COLLATE=C comm -23 -- - #{deploy_to.shellescape}/REQUIRED_ASSETS
|
134
|
+
); do
|
135
|
+
echo "Removing unneeded asset: $f";
|
136
|
+
rm -f -- "$f";
|
137
|
+
done;
|
138
|
+
rm -f -- #{deploy_to.shellescape}/REQUIRED_ASSETS
|
139
|
+
CMD
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
desc <<-DESC
|
144
|
+
Rolls back assets to the previous release by symlinking the release's manifest
|
145
|
+
to shared/assets/manifest.yml, and finally recompiling or regenerating nondigest assets.
|
146
|
+
DESC
|
147
|
+
task :rollback, :roles => assets_role, :except => { :no_release => true } do
|
148
|
+
previous_manifest = "#{previous_release}/assets_manifest.yml"
|
149
|
+
if capture("[ -e #{previous_manifest.shellescape} ] && echo true || echo false").strip != 'true'
|
150
|
+
puts "#{previous_manifest} is missing! Cannot roll back assets. " <<
|
151
|
+
"Please run deploy:assets:precompile to update your assets when the rollback is finished."
|
152
|
+
return false
|
153
|
+
else
|
154
|
+
run <<-CMD.compact
|
155
|
+
cd -- #{previous_release.shellescape} &&
|
156
|
+
cp -f -- #{previous_manifest.shellescape} #{shared_path.shellescape}/assets/manifest.yml &&
|
157
|
+
#{rake} RAILS_ENV=#{rails_env.shellescape} #{asset_env} assets:precompile:nondigest
|
158
|
+
CMD
|
159
|
+
end
|
160
|
+
end
|
59
161
|
end
|
60
162
|
end
|
@@ -83,10 +83,11 @@ module Capistrano
|
|
83
83
|
|
84
84
|
# Builds the set of authentication switches that perforce understands.
|
85
85
|
def authentication
|
86
|
-
[ p4port
|
87
|
-
p4user
|
88
|
-
p4passwd
|
89
|
-
p4client
|
86
|
+
[ p4port && "-p #{p4port}",
|
87
|
+
p4user && "-u #{p4user}",
|
88
|
+
p4passwd && "-P #{p4passwd}",
|
89
|
+
p4client && "-c #{p4client}",
|
90
|
+
p4charset && "-C #{p4charset}" ].compact.join(" ")
|
90
91
|
end
|
91
92
|
|
92
93
|
# Returns the command that will sync the given revision to the given
|
@@ -112,6 +113,10 @@ module Capistrano
|
|
112
113
|
def p4passwd
|
113
114
|
variable(:p4passwd) || variable(:scm_password)
|
114
115
|
end
|
116
|
+
|
117
|
+
def p4charset
|
118
|
+
variable(:p4charset)
|
119
|
+
end
|
115
120
|
|
116
121
|
def p4sync_flags
|
117
122
|
variable(:p4sync_flags) || "-f"
|
data/lib/capistrano/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.14.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2013-01-10 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: highline
|