In a Rails 4 app, I want precompiled assets to have copies of some assets to be available with a non fingerprinted filename. The app is deployed on Heroku.
I have the following rake task in place:
namespace :app do
task :nonfingerprint_assets => :environment do
manifests = Rails.application.config.assets[:precompile]
manifests = manifests.slice(1, manifests.length)
assets = Dir.glob(File.join(Rails.root, 'public/assets/**/*'))
regex = /(-{1}[a-z0-9]{32}*\.{1}){1}/
assets.each do |file|
next if File.directory?(file) || file !~ regex
source = file.split('/')
source.push(source.pop.gsub(regex, '.'))
non_digested = File.join(source)
if manifests.any? {|m|
if m.is_a? Regexp
m.match non_digested
else
m.ends_with?(non_digested)
end
}
puts "** copy source: #{file}"
puts "** copy destination: #{non_digested}"
FileUtils.cp(file, non_digested)
end
end
end
end
Rake::Task['assets:precompile'].enhance do
puts "Invoke nonfingerprint_assets"
Rake::Task['app:nonfingerprint_assets'].invoke
end
This rake task is working fine on my local machine even in production environment. It creates a file in public/assets/application.js which is the copy of the same file with a digest in its name.
When I deploy this code to heroku I get the following error message which I don't understand:
-----> Preparing app for Rails asset pipeline
Running: rake assets:precompile
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_
locales = false to avoid this message.
Invoke nonfingerprint_assets
** copy source: /tmp/build_48b86bff-83f9-4d21-8b21-712c1baef811/public/assets/application-51d1660b66655782ab137ee98c789fdd.js
** copy destination: /tmp/build_48b86bff-83f9-4d21-8b21-712c1baef811/public/assets/application.js
rake aborted!
No such file or directory - /tmp/build_48b86bff-83f9-4d21-8b21-712c1baef811/public/assets/application.js
/tmp/build_48b86bff-83f9-4d21-8b21-712c1baef811/lib/tasks/production.rake:26:in `block (3 levels) in <top (required)>'
/tmp/build_48b86bff-83f9-4d21-8b21-712c1baef811/lib/tasks/production.rake:9:in `each'
/tmp/build_48b86bff-83f9-4d21-8b21-712c1baef811/lib/tasks/production.rake:9:in `block (2 levels) in <top (required)>'
/tmp/build_48b86bff-83f9-4d21-8b21-712c1baef811/lib/tasks/production.rake:45:in `block in <top (required)>'
Tasks: TOP => app:nonfingerprint_assets
(See full trace by running task with --trace)
Please help me to understand what's going on.
Related
On Rails 6 (6.1.4.1) we had a RakeFile that would run a subset of tests. For example:
# lib/tasks/carrier.rake
namespace :test do
task carriers: "test:prepare" do
$: << "test"
test_files = FileList["test/models/carrier_test.rb",
"test/controllers/admin/carriers/**/*_test.rb",
"test/system/admin/carriers/**/*_test.rb"]
Rails::TestUnit::Runner.run(test_files)
end
end
This would execute just fine when called:
rails test:carriers
However, somewhere along the way, something changed and we began seeing errors when trying to run our RakeFile test tasks. (I haven't tracked down exactly what changed and when it changed -- perhaps it was part of the Rails 7 release.) Here's the error we began seeing:
rails aborted!
NameError: uninitialized constant Shoulda
Shoulda::Matchers.configure do |config|
^^^^^^^
/path/test/test_helper.rb:15:in `<main>'
/path/test/models/carrier_test.rb:1:in `<main>'
/path/lib/tasks/carriers.rake:11:in `block (2 levels) in <main>'
Tasks: TOP => test:carriers
(See full trace by running task with --trace)
The error appeared with no changes to our tests or environment configuration. (Running a full rake worked just fine.)
When reviewing the source code for Rails::TestUnit::Runner, I came across rake_run. Simply replacing Rails::TestUnit::Runner.run with Rails::TestUnit::Runner.rake_run addressed the issue (no other changes required):
# lib/tasks/carrier.rake
namespace :test do
task carriers: "test:prepare" do
$: << "test"
test_files = FileList["test/models/carrier_test.rb",
"test/controllers/admin/carriers/**/*_test.rb",
"test/system/admin/carriers/**/*_test.rb"]
Rails::TestUnit::Runner.rake_run(test_files)
end
end
Solution:
Added the following to the bottom of deploy.rb
Rake::Task["deploy:assets:restore_manifest"].clear_actions
before 'deploy:finishing_rollback', 'deploy:pre_start_precompile'
task :pre_start_precompile do
on roles(:db) do
with rails_env: "#{fetch(:stage)}" do
path_to_bundler = "/usr/local/rbenv/shims/bundle"
execute "cd #{release_path}; RAILS_ENV=production #{path_to_bundler} exec rake assets:precompile"
end
end
end
This worked!
Original question:
I'm running Rails 4.2 and Ruby 2.5.8 and capistrano 3.14.1. When I try and roll back I get this error;
** Execute bundler:install
00:04 bundler:install
The Gemfile's dependencies are satisfied, skipping installation
** Execute deploy:reverted
** Invoke deploy:rollback_assets (first_time)
** Invoke deploy:set_rails_env
** Execute deploy:rollback_assets
** Invoke deploy:assets:restore_manifest (first_time)
** Execute deploy:assets:restore_manifest
00:04 deploy:assets:restore_manifest
WARN Rails assets manifest file (or backup file) not found.
#<Thread:0x00007ff7f8218548#/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:10 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
1: from /home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute': Exception while executing as user#<server ip>: Rails assets manifest file (or backup file) not found. (SSHKit::Runner::ExecuteError)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as <user>#<server ip>: Rails assets manifest file (or backup file) not found.
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute'
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'
Caused by:
Capistrano::FileNotFound: Rails assets manifest file (or backup file) not found.
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/capistrano-rails-1.6.1/lib/capistrano/tasks/assets.rake:103:in `block (5 levels) in <top (required)>'
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/backends/abstract.rb:92:in `within'
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/capistrano-rails-1.6.1/lib/capistrano/tasks/assets.rake:90:in `block (4 levels) in <top (required)>'
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/backends/abstract.rb:31:in `instance_exec'
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/backends/abstract.rb:31:in `run'
/home/map7/.rbenv/versions/2.5.8/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:12:in `block (2 levels) in execute'
Tasks: TOP => deploy:assets:restore_manifest
I read somewhere that I have to make two files on the production server which I have and it didn't make a difference;
$ touch public/assets/.manifest.json
$ touch public/assets/.sprockets-manifest.json
The error happens within assets.rake part of capistrano-rails;
task :restore_manifest do
on release_roles(fetch(:assets_roles)) do
within release_path do
targets = detect_manifest_path.split(' ')
sources = targets.map do |target|
release_path.join('assets_manifest_backup', File.basename(target))
end
if test(:ls, *sources) && test(:ls, *targets) # <-- this line
source_map = sources.zip(targets)
source_map.each do |source, target|
execute :cp, source, target
end
else
msg = 'Rails assets manifest file (or backup file) not found.'
warn msg
fail Capistrano::FileNotFound, msg
end
end
end
end
I manually tested sources and targets. I found sources failed and targets passed. Below are both;
(byebug) sources
[#<Pathname:/var/www/<site>.com.au/releases/20201004053756/assets_manifest_backup/.sprockets-manifest-2df820954d56273c97d9696e88075409.json>, #<Pathname:/var/www/<site>.com.au/releases/20201004053756/assets_manifest_backup/.sprockets-manifest.json>]
(byebug) targets
["/var/www/<site>.com.au/releases/20201004053756/public/assets/.sprockets-manifest-2df820954d56273c97d9696e88075409.json", "/var/www/<site>.com.au/releases/20201004053756/public/assets/.sprockets-manifest.json"]
Update: listing of shared/public
[capistrano root]/shared/public$ find .
.
./system
./assets
./assets/application-e02d56bdf7493178ee13a95f4211508873eedfc4dbcff55cda9447e26b589ad0.js
./assets/application-04fbdaf9d6b9abbae40cd5dbc0a71ca7094b363cf5016d06db76b7018a397231.css
./assets/application-04fbdaf9d6b9abbae40cd5dbc0a71ca7094b363cf5016d06db76b7018a397231.css.gz
./assets/.sprockets-manifest-2df820954d56273c97d9696e88075409.json
./assets/application-81e70a4729ca29787e86c6981d9275dedbedddab40a87dfbcc39e19c9851c7b6.css
./assets/application-89cedfcf3e9592cd9f252337803bc10a9e57d40dc7fa8e192f2a4a32ef109b0c.js.gz
./assets/application-89cedfcf3e9592cd9f252337803bc10a9e57d40dc7fa8e192f2a4a32ef109b0c.js
./assets/application-e02d56bdf7493178ee13a95f4211508873eedfc4dbcff55cda9447e26b589ad0.js.gz
./assets/application-9416e76266dcf39961fba3ae76d96e7e89ce9e0eba1a0ccf529aa003869cac9d.css
./assets/.manifest.json
./assets/.sprockets-manifest.json
./assets/application-9416e76266dcf39961fba3ae76d96e7e89ce9e0eba1a0ccf529aa003869cac9d.css.gz
./assets/application-81e70a4729ca29787e86c6981d9275dedbedddab40a87dfbcc39e19c9851c7b6.css.gz
When I run bundle exec rake db:setup I get an error saying that rake doesn't know how to build that task. I then run bundle exec rake -T and see that db tasks are missing (all output below). How can I access the db tasks?
--application.rb--
require File.expand_path('../boot', __FILE__)
require 'rails'
require 'active_model/railtie'
require 'active_job/railtie'
require 'action_controller/railtie'
require 'action_view/railtie'
require 'sprockets/railtie'
Bundler.require(*Rails.groups)
module LofocatsUi
class Application < Rails::Application
end
end
--rake command--
bos-mp478:lofocats_ui rabdelaz$ bundle exec rake db:setup --trace
rake aborted!
Don't know how to build task 'db:setup' (See the list of available tasks with `rake --tasks`)
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/task_manager.rb:59:in `[]'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:159:in `invoke_task'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:116:in `each'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:116:in `block in top_level'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:125:in `run_with_threads'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:110:in `top_level'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:83:in `block in run'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/lib/rake/application.rb:80:in `run'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/gems/rake-12.3.2/exe/rake:27:in `<top (required)>'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/bin/rake:23:in `load'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#lofocats-ui/bin/rake:23:in `<top (required)>'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/cli/exec.rb:74:in `load'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/cli/exec.rb:74:in `kernel_load'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/cli/exec.rb:28:in `run'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/cli.rb:424:in `exec'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/cli.rb:27:in `dispatch'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/cli.rb:18:in `start'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/bin/bundle:30:in `block in <main>'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/lib/ruby/site_ruby/2.4.0/bundler/friendly_errors.rb:124:in `with_friendly_errors'
/Users/rabdelaz/.rvm/rubies/ruby-2.4.3/bin/bundle:22:in `<main>'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#global/bin/ruby_executable_hooks:24:in `eval'
/Users/rabdelaz/.rvm/gems/ruby-2.4.3#global/bin/ruby_executable_hooks:24:in `<main>'
--tasks list--
bos-mp478:lofocats_ui rabdelaz$ bundle exec rake -T
rake about # List versions of all Rails frameworks and the environment
rake assets:clean[keep] # Remove old compiled assets
rake assets:clobber # Remove compiled assets
rake assets:environment # Load asset compile environment
rake assets:precompile # Compile all the assets named in config.assets.precompile
rake cache_digests:dependencies # Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)
rake cache_digests:nested_dependencies # Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)
rake doc:app # Generate docs for the app -- also available doc:rails, doc:guides (options: TEMPLATE=/rdoc-template.rb, TITLE="Custom Title")
rake log:clear # Truncates all *.log files in log/ to zero bytes (specify which logs with LOGS=test,development)
rake middleware # Prints out your Rack middleware stack
rake notes # Enumerate all annotations (use notes:optimize, :fixme, :todo for focus)
rake notes:custom # Enumerate a custom annotation, specify with ANNOTATION=CUSTOM
rake rails:template # Applies the template supplied by LOCATION=(/path/to/template) or URL
rake rails:update # Update configs and some other initially generated files (or use just update:configs or update:bin)
rake routes # Print out all defined routes in match order, with names
rake secret # Generate a cryptographically secure secret key (this is typically used to generate a secret for cookie sessions)
rake stats # Report code statistics (KLOCs, etc) from the application or engine
rake time:zones:all # Displays all time zones, also available: time:zones:us, time:zones:local -- filter with OFFSET parameter, e.g., OFFSET=-6
rake tmp:clear # Clear session, cache, and socket files from tmp/ (narrow w/ tmp:sessions:clear, tmp:cache:clear, tmp:sockets:clear)
rake tmp:create # Creates tmp directories for sessions, cache, sockets, and pids
The following command is supposed to create a new database.
rails db:create
Where is this function defined? Or is this a pre-packaged function in rails?
It's in the databases.rake file of the framework:
namespace :create do
task all: :load_config do
ActiveRecord::Tasks::DatabaseTasks.create_all
end
ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
desc "Create #{spec_name} database for current environment"
task spec_name => :load_config do
db_config = ActiveRecord::DatabaseConfigurations.config_for_env_and_spec(Rails.env, spec_name)
ActiveRecord::Tasks::DatabaseTasks.create(db_config.config)
end
end
end
Whenever you doubt or want to know where a task has been defined, you can use the rails -W (or rake) command, passing the task:
$ rails -W db:create
rails db:create /path/databases.rake:26:in `block in <top (required)>'
rails db:create:all /path/databases.rake:20:in `block (2 levels) in <top (required)>'
Note it was introduced in the version 0.9 of Rake. This might or might not work depending on the versions which you're working with.
I have this rake task in a Rails 3.2.11 application in lib/rake/searches.rb:
namespace :searches do
desc "Start background searches"
task :start => :environment do
Rails.logger.info "Starting searches..."
Campaign.all.each do |c|
next unless c.recurring?
Rails.logger.info "Starting searches for campaign '#{c.name}'"
SearchWorker.enqueue(:campaign_id => c.id, :clear => true)
end
end
end
When I run it locally everything goes well. When I run it in production it errors out:
$ bundle exec rake searches:start
rake aborted!
uninitialized constant SearchWorker
/var/apps/web/lib/tasks/searches.rake:9:in `block (3 levels) in <top (required)>'
/var/apps/web/lib/tasks/searches.rake:5:in `block (2 levels) in <top (required)>'
Tasks: TOP => searches:start
(See full trace by running task with --trace)
When I jump into a console session, I can see that the class is correctly auto loaded:
$ bundle exec rails console
Loading production environment (Rails 3.2.11)
irb(main):001:0> SearchWorker
=> SearchWorker
This workers live in app/workers and they are added to the autoload_paths config setting in application.rb:
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
config.autoload_paths += %W(
#{config.root}/custom_scripts
#{config.root}/app/workers
#{config.root}/app/models/filters
)
So I have no clue why the error only occurs in production, and when running from a rake task.
Any ideas?
It seems you have created the rake file with .rb extension
lib/rake/searches.rb
can you try changing it to
lib/rake/searches.rake
That should work
This is due to the production environment in Rails 3.2 not being fully loaded, after the :environment task is complete.
If you explicitly require SearchWorker ie.
require 'app/workers/search_worker'
Within the beginning of the task block, it'll work.
(Why auto-loads isn't doing this for you, I don't know)