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 CHANGED
@@ -1,5 +1,10 @@
1
- ## 2.13.5 (tentative) / October 26 2012
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)
@@ -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? || self.class.ui.output_cols > 80 )
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
- ((self.instance_methods & Kernel.methods) - Namespaces::Namespace.instance_methods).each do |name|
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.method(name).owner == Kernel
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 'benchmark'
2
- require 'yaml'
3
- require 'shellwords'
4
- require 'capistrano/recipes/deploy/scm'
5
- require 'capistrano/recipes/deploy/strategy'
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(" ").shellescape} -exec touch -t -- #{stamp} {} ';'; true", :env => { "TZ" => "UTC" }) if asset_paths.any?
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', 'deploy:assets:symlink'
10
- after 'deploy:update_code', 'deploy:assets:precompile'
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 "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile"
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 && "-p #{p4port}",
87
- p4user && "-u #{p4user}",
88
- p4passwd && "-P #{p4passwd}",
89
- p4client && "-c #{p4client}" ].compact.join(" ")
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"
@@ -1,8 +1,8 @@
1
1
  module Capistrano
2
2
  class Version
3
3
  MAJOR = 2
4
- MINOR = 13
5
- PATCH = 5
4
+ MINOR = 14
5
+ PATCH = 1
6
6
 
7
7
  def self.to_s
8
8
  "#{MAJOR}.#{MINOR}.#{PATCH}"
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.13.5
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: 2012-10-26 00:00:00.000000000 Z
13
+ date: 2013-01-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: highline