capistrano3: Don't know how to build task 'deploy:create_db' - ruby-on-rails

I use capistrano3 to deploy my rails app.
deploy.rb
namespace :deploy do
after "deploy", "deploy:create_db"
after "deploy", "deploy:migrate"
after "finishing", "deploy:restart"
task :restart do
on roles(:web) do
execute "mkdir -p #{current_path}/tmp"
execute "touch #{current_path}/tmp/restart.txt"
end
end
task :create_db do
on roles(:web) do
execute "cd #{current_path}; bundle exec rake db:create RAILS_ENV=#{rails_env}"
end
end
end
When I run cap -T, the error occurred as below:
(Backtrace restricted to imported tasks)
cap aborted!
Don't know how to build task 'deploy:create_db'
(See full trace by running task with --trace)
cap -T --trace
** Invoke load:defaults (first_time)
** Execute load:defaults
cap aborted!
Don't know how to build task 'deploy:create_db'
/Library/Ruby/Gems/2.0.0/gems/rake-10.4.2/lib/rake/task_manager.rb:62:in `[]'
/Library/Ruby/Gems/2.0.0/gems/rake-10.4.2/lib/rake/task.rb:353:in `[]'
/Library/Ruby/Gems/2.0.0/gems/capistrano-3.3.5/lib/capistrano/dsl/task_enhancements.rb:12:in `after'
/Users/liuxingqi/Public/Spar/config/deploy.rb:53:in `block in <top (required)>'
Hope someone can help me, Thanks in advance!!!

I think you should define tasks first...
Try this:
namespace :deploy do
task :restart do
on roles(:web) do
execute "mkdir -p #{current_path}/tmp"
execute "touch #{current_path}/tmp/restart.txt"
end
end
task :create_db do
on roles(:web) do
execute "cd #{current_path}; bundle exec rake db:create RAILS_ENV=#{rails_env}"
end
end
after "deploy", "deploy:create_db"
after "deploy", "deploy:migrate"
after "finishing", "deploy:restart"
end

Related

Run rake task from Capistrano if it exists

I need to a create a Capistrano pre-deploy step that runs a custom rake task.
in deploy.rb:
before 'deploy:starting', 'db:rollback_staging'
namespace :db do
desc 'Rollback staging db only if PR already deployed requires rollback'
task :rollback_staging do
on roles(:master) do
within current_path.to_s do
with rails_env: 'staging' do
execute :rake, 'release:rollback_staging'
end
end
end
end
end
The problem is that when deploying this code the rake task is not yet present on the server and therefore deploy fails with:
rake stdout: rake aborted!
Don't know how to build task 'release:rollback_staging' (See the list of available tasks with `rake --tasks`)
If there a way to check if the rake task exists from Capistrano?
smth like:
with rails_env: 'staging' do
execute :rake, 'release:rollback_staging' if rake_exists? 'release:rollback_staging'
end
I ended up just ignoring not 0 exit code from a rake task using raise_on_non_zero_exit: false:
with rails_env: 'staging' do
execute :rake, 'release:rollback_staging', raise_on_non_zero_exit: false
end
Would this work? Saw this pattern in https://github.com/AgileConsultingLLC/capistrano3-delayed-job
if Rake::Task.task_defined?('release:rollback_staging')

What does the rake task db:full_reset do?

I have the following in my deploy script in which I inherited from other devs. Does any one know what the rake task db:full_reset does? I would think it resets the db but I can't find that actual task anywhere in the code. Running rake -T doesn't give any clues. Would it be located in a gem?
namespace :db do
task :full_reset do
on roles(:app) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :bundle, "exec rake db:full_reset"
end
end
end
end
end
You can use rake -W db:full_reset to see where that task is defined

Why I'm getting "undefined local variable or method `rails_env'"?

I'm getting undefined local variable or method 'rails_env'when doing
execute "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:stop"
I'm not a big capistrano or rails expert.
On deploy.rb I have
namespace :solr do
desc "start solr"
task :start do
on roles(:app) do
execute "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:start"
end
end
desc "stop solr"
task :stop do
on roles(:app) do
execute "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake sunspot:solr:stop"
end
end
desc "reindex the whole database"
task :reindex do
on roles(:app) do
invoke 'solr:stop'
execute "rm -rf #{shared_path}/solr/data/*"
invoke 'solr:start'
execute "cd #{current_path} && RAILS_ENV=#{rails_env} d"
end
end
desc "Symlink in-progress deployment to a shared Solr index"
task :symlink do
on roles(:app) do
execute "ln -s #{shared_path}/solr/data/ #{release_path}/solr/data"
execute "ln -s #{shared_path}/solr/pids/ #{release_path}/solr/pids"
invoke 'solr:reindex'
end
end
end
after "deploy:finishing", "solr:symlink"
And on deploy/staging.rb I have
set :rails_env, :staging
What's missed?
You should use fetch method. So, instead of rails_env use:
fetch(:rails_env)
Here (or here) is more details.
Try replacing rails_env with Rails.env

Capistrano deployment behaviour

I have this deploy.rb
after 'deploy:update_code', 'deploy:symlink_db', 'deploy:symlink_email'
after 'deploy:setup', 'setup:create_db_configuration', 'setup:create_email_configuration'
namespace :deploy do
desc "Symlinks the email.yml"
task :symlink_email, :roles => :app do
puts "##Sybolic Link the email.yml"
run "ln -nfs #{deploy_to}/shared/config/email.yml #{release_path}/config/email.yml"
end
desc "Symlinks the database.yml"
task :symlink_db, :roles => :app do
puts "##Sybolic Link the database.yml"
run "ln -nfs #{deploy_to}/shared/config/database.yml #{release_path}/config/database.yml"
end
But when I deploy, after the deploy:update_code it starts with
2013-07-27 03:30:30 executing `deploy:assets:symlink'
then
2013-07-27 03:30:32 executing `deploy:assets:precompile'
And when execution
executing "cd -- /home/ubuntu/deployments/saleshub/releases/20130727013023 && RAILS_ENV=production RAILS_GROUPS=assets rake assets:precompile"
It fails, because the symbolic links were not created yet. How do I make sure the my tasks to create the symlinks before compiling the assets?
before 'deploy:assets:precompile', 'deploy:symlink_db', 'deploy:symlink_email'

No such file or directory during cap deploy:update

I noticed in the output from cap deploy:update, that it is triggering "deploy:assets:precompile" as an after callback for deploy:update_code:
triggering after callbacks for `deploy:update_code'
* 2013-05-15 11:32:16 executing `deploy:assets:precompile'
triggering before callbacks for `deploy:assets:precompile'
* 2013-05-15 11:32:16 executing `deploy:assets:update_asset_mtimes'
* executing "[ -e /home/johnmerlino/public_html/store.johnmerlino.com/shared/assets/manifest* ] && cat /home/johnmerlino/public_html/store.johnmerlino.com/shared/assets/manifest* || echo"
servers: ["xxx.xx.xx.xxx"]
[xxx.xx.xx.xxx] executing command
command finished in 314ms
* executing "cd -- /home/johnmerlino/public_html/store.johnmerlino.com/releases/20130515153214 && bundle exec rake RAILS_ENV=production RAILS_GROUPS=assets assets:precompile"
servers: ["xxx.xx.xx.xxx"]
[xxx.xx.xx.xxx] executing command
** [out :: xxx.xx.xx.xxx] rake aborted!
** [out :: xxx.xx.xx.xxx] No such file or directory - /home/johnmerlino/public_html/store.johnmerlino.com/releases/20130515153214/config/config.yml
** [out :: xxx.xx.xx.xxx
Now the problem there is it says that the latest release doesn't have a "config.yml" file.
Actually in my capistrano script, that file is created after "deploy:update_code":
after "deploy:update_code", "deploy:symlink_shared_configs"
namespace :deploy do
desc "Symlink configuration files"
task :symlink_shared_configs, :roles => [:db,:app] do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
run "ln -nfs #{shared_path}/config/config.yml #{release_path}/config/config.yml"
end
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
So shouldn't config.yml be created by this time?
If both are being triggered in the list of callbacks for after deploy:update_code then they're essentially part of the same callback group, but the order in which callbacks in the same group are called depends on the implementation of the callback registration and execution.
If you need them to run in a given order then you can explicitly change when assets:precompile is run by moving it later, or moving the config.yml file earlier in order to guarantee that one comes before the other.
As it stands now, since they both run in the after deploy:update_code the order in which they get executed could be either:
...before...
deploy:update_code
...after... | after group
deploy:symlink_shared_configs | after group
deploy:assets:precompile | after group
...OR...
...before...
deploy:update_code
...after... | after group
deploy:assets:precompile | after group
deploy:symlink_shared_configs | after group
...and based on the fact that you've posted this question, it sounds like the latter instance is happening for you.

Resources