Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run custom rake task via capistrano 3?

which way, i can run rake commands via capistrano on remote server.

for example i have a lib/task/reparse.rake with some methods

desc "it's take csv file, makes some changes and fill db with this info"
task :example1 => :environment do
  require 'csv'
  rows_to_insert = []
  # some actions
  # ...
end

on local server all is fine - i just run rake reparse:example1 and it's work(fill db correctly). so question is - how can i run this command on real hosting, after deploy?

i'am using rails 4.1 + capistrano 3.

P.S. examples from site not work for me How do I run a rake task from Capistrano?

if i try cap production rake:invoke task=reparse:land it fails with:

cap aborted!
Don't know how to build task 'rake:invoke'

some fixes

namespace :somenamespace do
  task :runrake do  
    on roles(:all), in: :sequence, wait: 5 do      
      within release_path do
        execute :rake, ENV['task'], "RAILS_ENV=production"
      end 
    end
  end
end

with such way it begin to execute via

cap production somenamespace:runrake task=custom_task_file:custom_method1
like image 917
kpblc Avatar asked May 23 '14 12:05

kpblc


4 Answers

you need to load a custom rake task in Capistrano config:

# config/deploy.rb || config/deploy/production.rb
load 'lib/task/reparse.rake'

check for new task in console cap -T

like image 113
Semjon Avatar answered Nov 08 '22 05:11

Semjon


Based on the capistrano/rails gem: https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake

namespace :somenamespace do
  task :runrake do
    on roles(:all) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, ask :task
        end
      end 
    end
  end
end
like image 30
Kukunin Avatar answered Nov 08 '22 06:11

Kukunin


You can create a corresponding capistrano task to run a specific rake task like that:

namespace :guests do
  desc 'Remove guest users older than 7 days'
  task :clean do
    on roles(:app) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, 'guests:delete_old_guest_users'
        end
      end
    end
  end
end
like image 32
gugl Avatar answered Nov 08 '22 05:11

gugl


So I have been working on this. it seams to work well. However you need a formater to really take advantage of the code.

If you don't want to use a formatter just set the log level to to debug mode.

SSHKit.config.output_verbosity = Logger::DEBUG

Cap Stuff

namespace :invoke do
  desc 'Run a bash task on a remote server. cap environment invoke:bash[\'ls -la\'] '
  task :bash, :execute do |_task, args|
    on primary :app do
      within deploy_to do
        with rails_env: fetch(:rails_env) do
          SSHKit.config.format = :supersimple
          execute args[:execute]
        end
      end
    end
  end

  desc 'Run a rake task on a remote server. cap environment invoke:rake[\'db:migrate\'] '
  task :rake, :task do |_task, args|
    on primary :app do
      within current_path do
        with rails_env: fetch(:rails_env) do
          SSHKit.config.format = :supersimple
          rake args[:task]
        end
      end
    end
  end
end

This is the formatter I built to work with the code above. It is based off the :textsimple built into the sshkit but it is not a bad way to invoke custom tasks. Oh this many not works with the newest version of sshkit gem. I know it works with 1.7.1. I say this because the master branch has changed the SSHKit::Command methods that are available.

module SSHKit
  module Formatter
    class SuperSimple < SSHKit::Formatter::Abstract
      def write(obj)
        case obj
        when SSHKit::Command    then write_command(obj)
        when SSHKit::LogMessage then write_log_message(obj)
        end
      end
      alias :<< :write

      private

      def write_command(command)
        unless command.started? && SSHKit.config.output_verbosity == Logger::DEBUG
          original_output << "Running #{String(command)} #{command.host.user ? "as #{command.host.user}@" : "on "}#{command.host}\n"
          if SSHKit.config.output_verbosity == Logger::DEBUG
            original_output << "Command: #{command.to_command}" + "\n"
          end
        end

        unless command.stdout.empty?
          command.stdout.lines.each do |line|
            original_output << line
            original_output << "\n" unless line[-1] == "\n"
          end
        end

        unless command.stderr.empty?
          command.stderr.lines.each do |line|
            original_output << line
            original_output << "\n" unless line[-1] == "\n"
          end
        end

      end

      def write_log_message(log_message)
        original_output << log_message.to_s + "\n"
      end
    end
  end
end
like image 36
newdark-it Avatar answered Nov 08 '22 06:11

newdark-it