Pergunta

Eu já tenho um deploy.rb que pode implantar meu app no ??meu servidor de produção.

Meu aplicativo contém uma tarefa rake personalizada (um arquivo .rake no diretório lib / tarefas).

Eu gostaria de criar uma tarefa tampa que será executado remotamente essa tarefa rake.

Foi útil?

Solução 2

run("cd #{deploy_to}/current && /usr/bin/env rake `<task_name>` RAILS_ENV=production")

Encontrado com Google - http : //ananelson.com/said/on/2007/12/30/remote-rake-tasks-with-capistrano/

O RAILS_ENV=production era uma pegadinha - Eu não penso nisso em primeiro lugar e não conseguia descobrir por que a tarefa não estava fazendo nada

.

Outras dicas

Um pouco mais explícito, na sua \config\deploy.rb, adicione fora de qualquer tarefa ou namespace:

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

Então, a partir /rails_root/, você pode executar:

cap staging rake:invoke task=rebuild_table_abc

... par de anos mais tarde ...

Tenha um olhar em trilhos de Capistrano plugin, você pode ver em https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake#L5-L14 pode ser algo como:

desc 'Runs rake db:migrate if migrations are set'
task :migrate => [:set_rails_env] do
  on primary fetch(:migration_role) do
    within release_path do
      with rails_env: fetch(:rails_env) do
        execute :rake, "db:migrate"
      end
    end
  end
end

Capistrano 3 versão genérica (executar qualquer tarefa rake)

A construção de uma versão genérica da resposta de Mirek Rusin:

desc 'Invoke a rake command on the remote server'
task :invoke, [:command] => 'deploy:set_rails_env' do |task, args|
  on primary(:app) do
    within current_path do
      with :rails_env => fetch(:rails_env) do
        rake args[:command]
      end
    end
  end
end

Exemplo de utilização: cap staging "invoke[db:migrate]"

Note que deploy:set_rails_env exige vem do capistrano-rails gem

Use Capistrano de estilo invocações de rake

Há uma maneira comum que vai "apenas trabalho" com require 'bundler/capistrano' e outras extensões que ancinho Modificar. Isso também irá trabalhar com ambientes de pré-produção, se você estiver usando vários estágios. A essência? Use configuração vars, se puder.

desc "Run the super-awesome rake task"
task :super_awesome do
  rake = fetch(:rake, 'rake')
  rails_env = fetch(:rails_env, 'production')

  run "cd '#{current_path}' && #{rake} super_awesome RAILS_ENV=#{rails_env}"
end

Use a capistrano-rake gem

Basta instalar o gem sem mexer com receitas Capistrano personalizados e executar tarefas rake desejados em servidores remotos como esta:

cap production invoke:rake TASK=my:rake_task

Full Disclosure: Eu escrevi

Eu pessoalmente uso na produção de um método auxiliar como este:

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

Isso permite executar tarefa rake semelhante a usar o método run (comando).


NOTA: É semelhante ao que Duke proposto, mas I:

  • uso latest_release vez de current_release - a partir de minha experiência é mais o que você espera ao executar um comando rake;
  • siga a convenção de nomenclatura de Rake e Capistrano (em vez de: cmd -> tarefa e ancinho -> run_rake)
  • não definir RAILS_ENV = # {RAILS_ENV} porque o lugar certo para defini-lo é a variável default_run_options. Por exemplo default_run_options [: env]! = { 'RAILS_ENV' => 'produção'} # -> DRY

Há uma jóia interessante cape que faz suas tarefas rake disponível como tarefas Capistrano, para que possa executá-los remotamente. cape está bem documentado, mas aqui está uma breve visão geral sobre como configurar i up.

Depois de instalar a gem, basta adicionar esta ao seu arquivo config/deploy.rb.

# config/deploy.rb
require 'cape'
Cape do
  # Create Capistrano recipes for all Rake tasks.
  mirror_rake_tasks
end

Agora, você pode executar tudo o que você rake tarefas localmente ou remotamente através cap.

Como um bônus adicional, cape permite que você defina como você deseja executar o seu tarefa rake local e remotamente (não mais bundle exec rake), basta adicioná-lo ao seu arquivo config/deploy.rb:

# Configure Cape to execute Rake via Bundler, both locally and remotely.
Cape.local_rake_executable  = '/usr/bin/env bundle exec rake'
Cape.remote_rake_executable = '/usr/bin/env bundle exec rake'
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 

Aqui está o que eu coloquei no meu deploy.rb para simplificar a execução de tarefas de rake. É um simples invólucro em torno método de Capistrano run ().

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

Então eu só executar qualquer tarefa rake assim:

rake 'app:compile:jammit'

Isso funcionou para mim:

task :invoke, :command do |task, args|
  on roles(:app) do
    within current_path do
      with rails_env: fetch(:rails_env) do
        execute :rake, args[:command]
      end
    end
  end
end

cap production "invoke[task_name]" Em seguida, basta executar

A maior parte é de acima resposta com um aumento menor para executar qualquer tarefa rake de Capistrano

Executar qualquer tarefa rake de 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

Isso também funciona:

run("cd #{release_path}/current && /usr/bin/rake <rake_task_name>", :env => {'RAILS_ENV' => rails_env})

Mais informações: Capistrano Run

Se você quer ser capaz de passar vários argumentos tentar isso (com base na resposta do marinosbern):

task :invoke, [:command] => 'deploy:set_rails_env' do |task, args|
  on primary(:app) do
    within current_path do
      with :rails_env => fetch(:rails_env) do
        execute :rake, "#{args.command}[#{args.extras.join(",")}]"
      end
    end
  end
end

Em seguida, você pode executar uma tarefa assim: cap production invoke["task","arg1","arg2"]

Então, eu tenho vindo a trabalhar sobre isso. costuras para funcionar bem. No entanto, você precisa de um formater para realmente tirar proveito do código.

Se você não quiser usar um formatador apenas definir o nível de registro para a modo de depuração. Estes semas para h

SSHKit.config.output_verbosity = Logger::DEBUG

Cap Material

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

Este é o formatador I construído para trabalhar com o código acima. Ele é baseado no: textsimple embutido no sshkit mas não é um mau caminho para invocar tarefas personalizadas. Oh isso muitos não funciona com a versão mais recente do gem sshkit. Eu sei que ele funciona com 1.7.1. Digo isto porque o branch master mudou a SSHKit :: métodos de comando que estão disponíveis.

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top