├── .gitignore ├── Gemfile ├── LICENSE.md ├── README.md ├── Rakefile ├── capistrano-faster-assets.gemspec └── lib ├── capistrano-faster-assets.rb └── capistrano ├── faster_assets.rb ├── faster_assets └── version.rb └── tasks └── faster_assets.rake /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | /vendor/ruby 19 | .idea 20 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in *.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Andrew Thal, Ruben Stranders 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included 11 | in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 18 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 19 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Capistrano::FasterAssets 2 | 3 | This gem speeds up asset compilation by skipping the assets:precompile task if none of the assets were changed 4 | since last release. 5 | 6 | Works *only* with Capistrano 3+. 7 | 8 | ### Installation 9 | 10 | Add this to `Gemfile`: 11 | 12 | group :development do 13 | gem 'capistrano', '~> 3.1' 14 | gem 'capistrano-rails', '~> 1.1' 15 | gem 'capistrano-faster-assets', '~> 1.0' 16 | end 17 | 18 | And then: 19 | 20 | $ bundle install 21 | 22 | ### Setup and usage 23 | 24 | Add this line to `Capfile`, after `require 'capistrano/rails/assets'` 25 | 26 | require 'capistrano/faster_assets' 27 | 28 | Configure your asset depedencies in deploy.rb if you need to check additional paths (e.g. if you have some assets in YOUR_APP/engines/YOUR_ENGINE/app/assets). Default paths are: 29 | 30 | set :assets_dependencies, %w(app/assets lib/assets vendor/assets Gemfile.lock config/routes.rb) 31 | 32 | ### Warning 33 | 34 | 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: 35 | 36 | ```coffee 37 | text = <%= helper.get_text %> 38 | ``` 39 | 40 | The assets might not get recompiled, even if they have to, as this gem only checks if the asset file has changed (which is probably the only safe/fast way to do this). 41 | 42 | ### More Capistrano automation? 43 | 44 | If you'd like to streamline your Capistrano deploys, you might want to check 45 | these zero-configuration, plug-n-play plugins: 46 | 47 | - [capistrano-unicorn-nginx](https://github.com/bruno-/capistrano-unicorn-nginx)
48 | no-configuration unicorn and nginx setup with sensible defaults 49 | - [capistrano-postgresql](https://github.com/bruno-/capistrano-postgresql)
50 | plugin that automates postgresql configuration and setup 51 | - [capistrano-rbenv-install](https://github.com/bruno-/capistrano-rbenv-install)
52 | would you like Capistrano to install rubies for you? 53 | - [capistrano-safe-deploy-to](https://github.com/bruno-/capistrano-safe-deploy-to)
54 | if you're annoyed that Capistrano does **not** create a deployment path for the 55 | app on the server (default `/var/www/myapp`), this is what you need! 56 | 57 | ### Bug reports and pull requests 58 | 59 | ...are very welcome! 60 | 61 | ### Thanks 62 | 63 | [@athal7](https://github.com/athal7) - for the original idea and implementation. See https://coderwall.com/p/aridag 64 | for more details 65 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /capistrano-faster-assets.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'capistrano/faster_assets/version' 5 | 6 | Gem::Specification.new do |gem| 7 | gem.name = "capistrano-faster-assets" 8 | gem.version = Capistrano::FasterAssets::VERSION 9 | gem.authors = ["Andrew Thal", "Ruben Stranders"] 10 | gem.email = ["athal7@me.com", "r.stranders@gmail.com"] 11 | gem.description = <<-EOF.gsub(/^\s+/, '') 12 | Speeds up asset compilation by skipping the assets:precompile task if none of the assets were changed since last release. 13 | 14 | Works *only* with Capistrano 3+. 15 | 16 | Based on https://coderwall.com/p/aridag 17 | EOF 18 | gem.summary = "Speeds up asset compilation if none of the assets were changed since last release." 19 | gem.homepage = "https://github.com/capistrano-plugins/capistrano-faster-assets" 20 | 21 | gem.files = `git ls-files`.split($/) 22 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 23 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 24 | gem.require_paths = ["lib"] 25 | 26 | gem.add_dependency "capistrano", ">= 3.1" 27 | gem.add_development_dependency "rake" 28 | end 29 | -------------------------------------------------------------------------------- /lib/capistrano-faster-assets.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/capistrano-plugins/capistrano-faster-assets/af3972964dcf1fe89de29b1298aa4f39532b9705/lib/capistrano-faster-assets.rb -------------------------------------------------------------------------------- /lib/capistrano/faster_assets.rb: -------------------------------------------------------------------------------- 1 | load File.expand_path("../tasks/faster_assets.rake", __FILE__) 2 | -------------------------------------------------------------------------------- /lib/capistrano/faster_assets/version.rb: -------------------------------------------------------------------------------- 1 | module Capistrano 2 | module FasterAssets 3 | VERSION = '1.1.0'.freeze 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/capistrano/tasks/faster_assets.rake: -------------------------------------------------------------------------------- 1 | # Original source: https://coderwall.com/p/aridag 2 | 3 | 4 | # set the locations that we will look for changed assets to determine whether to precompile 5 | set :assets_dependencies, %w(app/assets lib/assets vendor/assets Gemfile.lock config/routes.rb) 6 | 7 | # clear the previous precompile task 8 | Rake::Task["deploy:assets:precompile"].clear_actions 9 | class PrecompileRequired < StandardError; 10 | end 11 | 12 | namespace :deploy do 13 | namespace :assets do 14 | desc "Precompile assets" 15 | task :precompile do 16 | on roles(fetch(:assets_roles)) do 17 | within release_path do 18 | with rails_env: fetch(:rails_env) do 19 | begin 20 | # find the most recent release 21 | latest_release = capture(:ls, '-xr', releases_path).split[1] 22 | 23 | # precompile if this is the first deploy 24 | raise PrecompileRequired unless latest_release 25 | 26 | latest_release_path = releases_path.join(latest_release) 27 | 28 | # precompile if the previous deploy failed to finish precompiling 29 | execute(:ls, latest_release_path.join('assets_manifest_backup')) rescue raise(PrecompileRequired) 30 | 31 | fetch(:assets_dependencies).each do |dep| 32 | release = release_path.join(dep) 33 | latest = latest_release_path.join(dep) 34 | 35 | # skip if both directories/files do not exist 36 | next if [release, latest].map{|d| test "[ -e #{d} ]"}.uniq == [false] 37 | 38 | # execute raises if there is a diff 39 | execute(:diff, '-Nqr', release, latest) rescue raise(PrecompileRequired) 40 | end 41 | 42 | info("Skipping asset precompile, no asset diff found") 43 | 44 | # copy over all of the assets from the last release 45 | release_asset_path = release_path.join('public', fetch(:assets_prefix)) 46 | # skip if assets directory is symlink 47 | begin 48 | execute(:test, '-L', release_asset_path.to_s) 49 | rescue 50 | execute(:cp, '-r', latest_release_path.join('public', fetch(:assets_prefix)), release_asset_path.parent) 51 | end 52 | 53 | # check that the manifest has been created correctly, if not 54 | # trigger a precompile 55 | begin 56 | # Support sprockets 2 57 | execute(:ls, release_asset_path.join('manifest*')) 58 | rescue 59 | begin 60 | # Support sprockets 3 61 | execute(:ls, release_asset_path.join('.sprockets-manifest*')) 62 | rescue 63 | raise(PrecompileRequired) 64 | end 65 | end 66 | 67 | rescue PrecompileRequired 68 | execute(:rake, "assets:precompile") 69 | end 70 | end 71 | end 72 | end 73 | end 74 | end 75 | end 76 | --------------------------------------------------------------------------------