diff --git a/README.md b/README.md index 93f06e1..eb91720 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,6 @@ This gem speeds up asset compilation by skipping the assets:precompile task if none of the assets were changed since last release. -Works *only* with Capistrano 3+. - ### Installation Add this to `Gemfile`: @@ -24,7 +22,7 @@ And then: Add this line to `Capfile`, after `require 'capistrano/rails/assets'` require 'capistrano/faster_assets' - + ### Warning Please keep in mind, that if you use ERB in your assets, you might run into cases where Capistrano won't recompile assets when needed. For instance, let's say you have a CoffeeScript file like this: diff --git a/capistrano-faster-assets.gemspec b/capistrano-faster-assets.gemspec index be14fdb..b7bcd6a 100644 --- a/capistrano-faster-assets.gemspec +++ b/capistrano-faster-assets.gemspec @@ -11,8 +11,6 @@ Gem::Specification.new do |gem| gem.description = <<-EOF.gsub(/^\s+/, '') Speeds up asset compilation by skipping the assets:precompile task if none of the assets were changed since last release. - Works *only* with Capistrano 3+. - Based on https://coderwall.com/p/aridag EOF gem.summary = "Speeds up asset compilation if none of the assets were changed since last release." @@ -23,6 +21,6 @@ Gem::Specification.new do |gem| gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = ["lib"] - gem.add_dependency "capistrano", ">= 3.1" + gem.add_dependency "capistrano", ">= 2.0" gem.add_development_dependency "rake" end diff --git a/lib/capistrano/faster_assets.rb b/lib/capistrano/faster_assets.rb index f8ffca9..3e08e6f 100644 --- a/lib/capistrano/faster_assets.rb +++ b/lib/capistrano/faster_assets.rb @@ -1 +1,11 @@ -load File.expand_path("../tasks/faster_assets.rake", __FILE__) +module Capistrano + module FasterAssets + DEPENDENCIES = %w(app/assets lib/assets vendor/assets Gemfile.lock config/routes.rb) + end +end + +if Gem::Specification.find_by_name('capistrano').version >= Gem::Version.new('3.0.0') + load File.expand_path("../tasks/faster_assets.rake", __FILE__) +else + require_relative 'tasks/faster_assets' +end diff --git a/lib/capistrano/tasks/faster_assets.rake b/lib/capistrano/tasks/faster_assets.rake index 30e3f8f..490212a 100644 --- a/lib/capistrano/tasks/faster_assets.rake +++ b/lib/capistrano/tasks/faster_assets.rake @@ -1,8 +1,10 @@ +require "capistrano/faster_assets" + # Original source: https://coderwall.com/p/aridag # set the locations that we will look for changed assets to determine whether to precompile -set :assets_dependencies, %w(app/assets lib/assets vendor/assets Gemfile.lock config/routes.rb) +set :assets_dependencies, Capistrano::FasterAssets::DEPENDENCIES # clear the previous precompile task Rake::Task["deploy:assets:precompile"].clear_actions @@ -17,7 +19,7 @@ namespace :deploy do within release_path do with rails_env: fetch(:rails_env) do begin - # find the most recent release + # find the most recent release latest_release = capture(:ls, '-xr', releases_path).split[1] # precompile if this is the first deploy @@ -29,12 +31,12 @@ namespace :deploy do execute(:ls, latest_release_path.join('assets_manifest_backup')) rescue raise(PrecompileRequired) fetch(:assets_dependencies).each do |dep| - release = release_path.join(dep) - latest = latest_release_path.join(dep) - - # skip if both directories/files do not exist - next if [release, latest].map{|d| test "[ -e #{d} ]"}.uniq == [false] - + release = release_path.join(dep) + latest = latest_release_path.join(dep) + + # skip if both directories/files do not exist + next if [release, latest].map{|d| test "[ -e #{d} ]"}.uniq == [false] + # execute raises if there is a diff execute(:diff, '-Nqr', release, latest) rescue raise(PrecompileRequired) end diff --git a/lib/capistrano/tasks/faster_assets.rb b/lib/capistrano/tasks/faster_assets.rb new file mode 100644 index 0000000..9dca4ec --- /dev/null +++ b/lib/capistrano/tasks/faster_assets.rb @@ -0,0 +1,53 @@ +# Original source: https://coderwall.com/p/aridag + +require "capistrano/faster_assets" + +Capistrano::Configuration.instance(:must_exist).load do + # set the locations that we will look for changed assets to determine whether to precompile + _cset(:assets_dependencies) { Capistrano::FasterAssets::DEPENDENCIES } + _cset(:assets_manifest_basename) { "assets_manifest" } + + # Alias the base capistrano provided task so that we can still access it + alias_task("deploy:assets:force_precompile", "deploy:assets:precompile") + + def first_deploy? + previous_release.nil? + end + + def previous_release_failed_compilation? + previous_manifest_count = capture("ls -1 #{previous_release}/#{assets_manifest_basename}* | wc -l").to_i + + previous_manifest_count < 1 + end + + def asset_file_diff? + assets_dependencies.any? do |dep| + previous = "#{previous_release}/#{dep}" + latest = "#{release_path}/#{dep}" + + # skip if both directories/files do not exist + next if [previous, latest].any? { |path| result = capture("ls -1 #{path} | wc -l"); puts result; result.to_i < 1 } + + # if there are file diffs between the directories/files, return true + diff = capture("diff -Nqr #{previous} #{latest} | wc -l") + diff.to_i > 0 + end + end + + namespace :deploy do + namespace :assets do + desc <<-DESC + Override capistrano v2's deploy:assets:precompile to add a pre-check + for differences in asset files in subsequent relase before invoking + the task. + DESC + task :precompile, roles: lambda { assets_role }, except: { no_release: true } do + if !first_deploy? && !previous_release_failed_compilation? && !asset_file_diff? + logger.info("Skipping asset precompile, no asset diff found") + else + force_precompile + end + end + end + end +end