Capistrano3のタスク内でトップレベルのタスク名を取得する
Capistrano3でタスク書いていて、タスク内でcapコマンドとして実行されたトップレベルのタスク名を引いて、処理を分岐させる必要が生じて、そのトップレベルのタスク名取得に苦労したので、ここに備忘録化しておく。
基本的にCapistrano3でタスク内で自分のタスク名を取得したい場合、次のようにブロックの引数として引ける。
desc "main task"
task :main_task => :sub_task do |task|
run_locally do
info ": This task name: #{task}"
info ": Running main deploy task!"
end
end
desc "sub task"
task :sub_task do |task|
run_locally do
current_task = task.name_with_args.split(':').last
info ": This task name: #{current_task}"
end
end
上記タスクを実行してみると、こうなる。
$ cap test deploy:main_task
INFO: This task name: sub_task
INFO: This task name: deploy:main_task
INFO: Running main deploy task!
ただ、デプロイの共通設定を読み込むとかのサブタスクを作って、全てのメインタスクの前にそのサブタスクを実行するようなタスクチェーンを構築した場合に、特定のメインタスクが実行された時のみ、サブタスクの一部処理を分岐させたいとかの要望が発生すると、サブタスク内でメインタスクのタスク名を取得する必要が出てくる。つまりは、capコマンドで実行されるトップレベルタスク(例で言うところのメインタスク)を取得したいのだが、これがなかなかTIPSが見つからなくて実現するのに苦労した。 Capistranoのタスク処理は、コアで使われているRakeクラスで実現されているので、そのRakeクラスのApplicationメソッドから取得する必要があった。
トップレベルタスクを取得して処理分岐を行ったサブタスクの例:
desc "main task1 : initialize"
task :initialize => :set_options do
run_locally do
info ": Running initialization to deploy"
end
end
desc "main task2 : deployment"
task :deployment => :set_options do
run_locally do
info ": Running application deploy!"
end
end
desc "common sub task : set options"
task :set_options do |task|
set :top_level_task, task.application.top_level_tasks.last.split(':').last
run_locally do
info ": Top level task name: #{fetch(:top_level_task)}"
if (fetch(:top_level_task) == 'initialize') then
info ": If main-task is named initialize, this task running."
else
info ": Perform the task in the case of the main task of deployment."
end
end
end
上記タスクの実行結果は、
$ cap test deploy:initialize
INFO: Top level task name: initialize
INFO: If main-task is named initialize, this task running.
INFO: Running initialization to deploy
$ cap test deploy:deployment
INFO: Top level task name: deployment
INFO: Perform the task in the case of the main task of deployment.
INFO: Running application deploy!
と、サブタスクは1つでも実行されたトップレベルタスク(メインタスク)が異なるために処理が変わっていることがわかる。
タスクを切り出して共通化する時などは、Rake::Application.top_level_tasks
のメソッドは結構重宝する。