# Original source: https://coderwall.com/p/aridag # clear the previous precompile task Rake::Task["deploy:assets:precompile"].clear_actions class PrecompileRequired < StandardError; end set :assets_prefix, 'packs' namespace :deploy do namespace :assets do desc "Precompile assets" task :precompile do on roles(fetch(:assets_roles)) do within release_path do with rails_env: fetch(:rails_env) do begin # find the most recent release latest_release = File.basename(capture(:readlink, current_path)) # precompile if this is the first deploy raise PrecompileRequired unless latest_release latest_release_path = releases_path.join(latest_release) latest_node_modules_path = latest_release_path.join(fetch(:node_modules_path)) execute(:test, '-e', latest_node_modules_path.to_s) rescue raise PrecompileRequired release_node_modules_path = release_path.join(fetch(:node_modules_path)) begin execute(:test, '-L', release_node_modules_path.to_s) rescue execute(:cp, '-r', latest_node_modules_path, release_node_modules_path.parent) end # precompile if the previous deploy failed to finish precompiling 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] # execute raises if there is a diff execute(:diff, '-Nqr', release, latest) rescue raise(PrecompileRequired) end fetch(:assets_shared_dependencies).each do |dep| shared_file = shared_path.join(dep) execute(:test, latest_release_path, '-nt', shared_file) rescue raise(PrecompileRequired) end info("Skipping asset precompile, no asset diff found") # copy over all of the assets from the last release release_asset_path = release_path.join('public', fetch(:assets_prefix)) # skip if assets directory is symlink begin execute(:test, '-L', release_asset_path.to_s) rescue execute(:cp, '-r', latest_release_path.join('public', fetch(:assets_prefix)), release_asset_path.parent) end # copy assets if manifest file is not exist (this is first deploy after using symlink) execute(:ls, release_asset_path.join('manifest*')) rescue raise(PrecompileRequired) rescue PrecompileRequired execute(:rake, "assets:precompile") end end end end end end end namespace :load do task :defaults do set :assets_dependencies, fetch(:assets_dependencies, [ 'package.json', '.babelrc', '.postcssrc.yml', 'app/javascript', 'config/webpack', 'config/webpacker.yml', 'yarn.lock' ]) set :node_modules_path, fetch(:node_modules_path, 'node_modules') set :assets_shared_dependencies, fetch(:assets_shared_dependencies, []) end end