2

I followed the answer from @Coward in this topic: How do I run a rake task from Capistrano? to add a customizing task rake:invoke in my deploy.rb to be able to invoke rake tasks remotely.

It works perfect on it's own part, but I get following error when my cap deploy processing is doing assets:precompile

[mydomain.com] rvm_path=/usr/local/rvm /usr/local/rvm/bin/rvm-shell '1.9.2@ziya' -c 'cd /var/deploy/ziya/releases/20120223100338 && #<Capistrano::Configuration::Namespaces::Namespace:0x007ff2b4a4bad8> RAILS_ENV=staging RAILS_GROUPS=assets assets:precompile'
 ** [out :: my domain.com] bash: -c: line 1: syntax error: unexpected end of file
    command finished in 1265ms

it's like kind of injection something, but I just can't find out what's going wrong in my deploy.rb

deploy.rb:

$:.unshift(File.expand_path('./lib', ENV['rvm_path'])) # Add RVM's lib directory to the load path.
require "rvm/capistrano"                  # Load RVM's capistrano plugin.
set :rvm_ruby_string, '1.9.2@ziya'
set :use_sudo, true

require "bundler/capistrano"

set :stages, %w(staging production)
set :default_stage, "production"
require 'capistrano/ext/multistage'

set :application, "my application"

# ssh to the deploy server
default_run_options[:pty] = true

# setup scm:
set :repository,  "mygiturl"
set :deploy_via, :remote_cache
set :scm_username, "myusernmae"
set :scm, :git
set :scm_verbose, "true"
set :branch, "master"
ssh_options[:forward_agent] = true

set(:releases_path)     { File.join(deploy_to, version_dir) }
set(:shared_path)       { File.join(deploy_to, shared_dir) }
set(:current_path)      { File.join(deploy_to, current_dir) }
set(:release_path)      { File.join(releases_path, release_name) }

set :deploy_to, "/var/deploy/#{application}"

# If you are using Passenger mod_rails uncomment this:
namespace :deploy do
  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

  task :bootstrap do
    run "cd #{release_path}; rake bootstrap:all RAILS_ENV=#{rails_env}"
  end

  task :import_all do
    run "cd #{release_path}; rake import:pages RAILS_ENV=#{rails_env}"
    run "cd #{release_path}; rake import:legacy_all RAILS_ENV=#{rails_env}"
  end  

  task :import_pages do
    run "cd #{release_path}; rake import:pages RAILS_ENV=#{rails_env}"
  end
end

namespace :rake do  
  desc "Run a task on a remote server."  
  # run like: cap staging rake:invoke task=a_certain_task  
  task :invoke do  
    run("cd #{deploy_to}/current; /usr/bin/env rake #{ENV['task']} RAILS_ENV=#{rails_env}")  
  end  
end

But if I move the task :invoke into namespace :deploy, drop the namespace :rake, then everything is ok, it's so confusing..

Community
  • 1
  • 1
larryzhao
  • 3,173
  • 2
  • 40
  • 62

1 Answers1

2

This happen since Capistrano in its source declare rake as internal variable, in this way you can override which command is used as rake command line using a set :rake instruction in your deploy file.

However, because of capistrano internals, when you declare a rake namespace it will take precedence on the declared rake variable. So when capistrano execute its recipe to precompile assets and it builds the required command line the rake variable instead of returning the "rake" string returns your declared namespace converted to a string. You can see it in this part of the built command line:

 ... && #<Capistrano::Configuration::Namespaces::Namespace:0x007ff2b4a4bad8> RAILS_ENV=staging RAILS_GROUPS=assets assets:precompile'

This obviously cause a shell syntax error and this is the reason of why changing the namespace solves your issue.

Fabio
  • 18,856
  • 9
  • 82
  • 114