Question

J'ai déjà un fichier deploy.rb qui peut déployer mon application sur mon serveur de production.

Mon application contient une tâche de rake personnalisée (un fichier .rake dans le répertoire lib / tasks).

J'aimerais créer une tâche de plafonnement qui exécutera cette tâche de rake à distance.

Était-ce utile?

La solution 2

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

Je l'ai trouvé avec Google - http : //ananelson.com/said/on/2007/12/30/remote-rake-tasks-with-capistrano/

Le RAILS_ENV = production était un piège. Je n'y avais pas pensé au début et je ne pouvais pas comprendre pourquoi la tâche ne faisait rien.

Autres conseils

Un peu plus explicite, dans votre \ config \ deploy.rb , ajoutez en dehors de toute tâche ou espace de nom:

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

Ensuite, à partir de / rails_root / , vous pouvez exécuter:

cap staging rake:invoke task=rebuild_table_abc

... quelques années plus tard ...

Jetez un coup d’œil au plugin rails de capistrano. rel = "noreferrer"> https://github.com/capistrano/rails/blob/master/lib/capistrano/tasks/migrations.rake#L5-L14 , cela peut ressembler à:

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

Version générique de Capistrano 3 (exécuter une tâche de rake)

Construire une version générique de la réponse 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

Exemple d'utilisation: staging de cap " invoke [db: migrate] "

Notez que deploy: set_rails_env requiert provient de la gem capistrano-rails

Utiliser des invocations de rake de style Capistrano

Il existe un moyen courant de "travailler simplement". avec require 'bundler / capistrano' et d'autres extensions modifiant le rake. Cela fonctionnera également avec les environnements de pré-production si vous utilisez plusieurs étapes. L'essentiel? Utilisez les paramètres de configuration si vous le pouvez.

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

Utilisez le capistrano-rake bijou

Installez simplement la gemme sans manipuler les recettes capistrano personnalisées et exécutez les tâches de rake souhaitées sur des serveurs distants, comme suit:

cap production invoke:rake TASK=my:rake_task

Full Disclosure: je l'ai écrit

J'utilise personnellement dans la production une méthode d'assistance comme celle-ci:

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

Cela permet d'exécuter une tâche de rake similaire à l'utilisation de la méthode run (commande).

REMARQUE: Il est similaire à ce que Duc proposé, mais je:

  • utilisez latest_release au lieu de current_release - de par mon expérience, c’est plus ce à quoi vous vous attendez lors de l’exécution d’une commande rake;
  • suivez les conventions de nommage de Rake et Capistrano (au lieu de: cmd - > tâche et rake - > run_rake)
  • ne définissez pas RAILS_ENV = # {rails_env} car le bon endroit pour le définir est la variable default_run_options. E.g default_run_options [: env] = {'RAILS_ENV' = > 'production'} # - > SEC!

Il existe un bijou intéressant, cape , qui rend vos tâches de rake disponibles en tant que tâches Capistrano, afin que vous puissiez les exécuter. à distance. cape est bien documenté, mais voici un bref aperçu de la configuration.

Après avoir installé la gemme, ajoutez simplement ceci à votre fichier config / deploy.rb .

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

Maintenant, vous pouvez exécuter toutes vos tâches rake localement ou à distance via cap .

En prime, cape vous permet de définir la manière dont vous souhaitez exécuter votre tâche de rake localement et à distance (plus de bundle exec rake ), ajoutez-le simplement à votre Fichier 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 

Voici ce que j'ai mis dans le fichier deploy.rb pour simplifier l'exécution des tâches de rake. C'est un simple wrapper autour de la méthode run () de capistrano.

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

Ensuite, je lance juste n'importe quelle tâche de rake comme ceci:

rake 'app:compile:jammit'

Cela a fonctionné pour moi:

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

Ensuite, exécutez simplement cap production "invoke [nom_tâche]" & <; code>

.

La majeure partie provient de ci-dessus, réponse avec une amélioration mineure pour exécuter n'importe quelle tâche de capistrano

Exécutez n'importe quelle tâche de ratissage depuis 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

Cela fonctionne aussi:

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

Plus d'infos: Capistrano Run

Si vous voulez pouvoir passer plusieurs arguments, essayez ceci (d'après la réponse de 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

Vous pouvez ensuite exécuter une tâche comme suit: cap production appel ["tâche", "arg1", "arg2"]

Donc, j'ai travaillé sur cela. il semble bien fonctionner. Cependant, vous avez besoin d'un formateur pour vraiment tirer parti du code.

Si vous ne souhaitez pas utiliser un formateur, définissez simplement le niveau de journalisation sur le mode débogage. Ces semas à h

SSHKit.config.output_verbosity = Logger::DEBUG

Casquette

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

C’est le formateur que j’ai construit pour fonctionner avec le code ci-dessus. Il est basé sur la commande texto intégrée au sshkit, mais ce n’est pas un mauvais moyen d’appeler des tâches personnalisées. Oh, cela ne fonctionne pas avec la dernière version de sshkit gem. Je sais que cela fonctionne avec 1.7.1. Je dis cela parce que la branche principale a changé les méthodes SSHKit :: Command disponibles.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top