How do I run a rake task from Capistrano?

前端 未结 16 2076
忘了有多久
忘了有多久 2020-11-28 02:18

I already have a deploy.rb that can deploy my app on my production server.

My app contains a custom rake task (a .rake file in the lib/tasks directory).

I\

相关标签:
16条回答
  • 2020-11-28 02:26

    Use the capistrano-rake gem

    Just install the gem without messing with custom capistrano recipes and execute desired rake tasks on remote servers like this:

    cap production invoke:rake TASK=my:rake_task
    

    Full Disclosure: I wrote it

    0 讨论(0)
  • 2020-11-28 02:27
    namespace :rake_task do
      task :invoke do
        if ENV['COMMAND'].to_s.strip == ''
          puts "USAGE: cap rake_task:invoke COMMAND='db:migrate'" 
        else
          run "cd #{current_path} && RAILS_ENV=production rake #{ENV['COMMAND']}"
        end
      end                           
    end 
    
    0 讨论(0)
  • 2020-11-28 02:27

    Most of it is from above answer with a minor enhancement to run any rake task from capistrano

    Run any rake task from capistrano

    $ cap rake -s rake_task=$rake_task
    
    # Capfile     
    task :rake do
      rake = fetch(:rake, 'rake')
      rails_env = fetch(:rails_env, 'production')
    
      run "cd '#{current_path}' && #{rake} #{rake_task} RAILS_ENV=#{rails_env}"
    end
    
    0 讨论(0)
  • 2020-11-28 02:27

    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. These semas to h

    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 roles(:app), in: :sequence do
          SSHKit.config.format = :supersimple
          execute args[:execute]
        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
    
    0 讨论(0)
  • 2020-11-28 02:29

    Here's what I put in my deploy.rb to simplify running rake tasks. It's a simple wrapper around capistrano's run() method.

    def rake(cmd, options={}, &block)
      command = "cd #{current_release} && /usr/bin/env bundle exec rake #{cmd} RAILS_ENV=#{rails_env}"
      run(command, options, &block)
    end
    

    Then I just run any rake task like so:

    rake 'app:compile:jammit'
    
    0 讨论(0)
  • 2020-11-28 02:33

    I personally use in production a helper method like this:

    def run_rake(task, options={}, &block)
      command = "cd #{latest_release} && /usr/bin/env bundle exec rake #{task}"
      run(command, options, &block)
    end
    

    That allows to run rake task similar to using the run (command) method.


    NOTE: It is similar to what Duke proposed, but I:

    • use latest_release instead of current_release - from my experience it is more what you expect when running a rake command;
    • follow the naming convention of Rake and Capistrano (instead of: cmd -> task and rake -> run_rake)
    • don't set RAILS_ENV=#{rails_env} because the right place to set it is the default_run_options variable. E.g default_run_options[:env] = {'RAILS_ENV' => 'production'} # -> DRY!
    0 讨论(0)
提交回复
热议问题