开发者

How do I make a Rake Task run after all other tasks? (i.e. a Rake AfterBuild task)

I'm new to Rake and using it to build .net projects. What I'm interested in is having a Summary task that prints out a summary of what has been done. I want this task to always be called, no matter what tasks rake was invoked with.

Is there an easy way to accomplish this?

Thanks


Update on the question, responding to Patrick's answer what I want is the after task to run once after all other tasks, so the output I want is:

task :test1 do 
  puts 'test1'
end

task :test2 do 
  puts 'test2'
end

Rake::Task.tasks.each do |t|
    <Insert rake magic here>
#  t.enhance do 
#    puts 'after'
#  end
end

$ rake test1
test1
after

$rake test2
test2
after

$rake test1 test2  
test1
test2
after

and if

task :test3 =>[:test1, :test2]
   puts 'test3'
end

    $rake test3
test1
test2
test3
after

Ev开发者_如何学Goen though the bounty is gone, any further help much appreciated. (Sadily I don't think that I can offer another bounty.)


You should be able to do this with 'enhance':

Rake::Task["my_task"].enhance do
  Rake::Task["my_after_task"].invoke
end

This will cause 'my_after_task' to be invoked after 'my_task'.

If you want to apply this to all tasks, just loop over all the tasks and call enhance for each:

Rake::Task.tasks.each do |t| 
  t.enhance do 
    Rake::Task["my_after_task"].invoke
  end
end

Full test file:

task :test1 do 
  puts 'test1'
end

task :test2 do 
  puts 'test2'
end

Rake::Task.tasks.each do |t|
  t.enhance do 
    puts 'after'
  end
end

And the output:

$ rake test1
test1
after

$ rake test2
test2
after


Found this simple elegant answer here that uses the Ruby method at_exit.

It's worth noting that the method defined after at_exit will run every time the rake script is invoked regardless of the task run, or if any task is run. This includes when running rake -T (to list available tasks). Make sure that at_exit only does anything if a previous task told it to do so.

rakefile.rb

desc "Lovely task a"
task :a do
  puts "a"
end

desc "Lovely task b"
task :b do
  puts "b"
end

task :cleanup do
  puts "cleanup"
end

at_exit { Rake::Task[:cleanup].invoke if $!.nil? }

shell

$ rake a b
a
b
cleanup
$ rake -T
rake a # Lovely task a
rake b # Lovely task b
cleanup

You also don't need to make it run a task if you don't want to.

at_exit do
  puts "cleanup"
end

Or make it run an method

def on_exit_do_cleanup
  puts "cleanup"
end

at_exit { on_exit_do_cleanup }

And you may want to make sure you only do the cleanup if a task actually ran so that rake -T won't also do a cleanup.

rakefile.rb

do_cleanup = false

desc "Lovely task a"
task :a do
  puts "a"
  do_cleanup = true
end

desc "Lovely task b"
task :b do
  puts "b"
  do_cleanup = true
end

task :cleanup do
  return unless $!.nil? # No cleanup on error
  return unless do_cleanup # No cleanup if flag is false
  puts "cleanup"
end

at_exit { Rake::Task[:cleanup].invoke }


Posting this as a new answer to keep the other one available. This is much less elegant as I have to get into the guts of Rake and manually update the task list, but it works.

task :test1 do
  puts 'test1'
end

task :test2 do 
  puts 'test2'
end

task :after do
  puts 'after'
end

# top_level_tasks is't writable so we need to do this ugly
# instance_variable_set hack...
current_tasks =  Rake.application.top_level_tasks
current_tasks << :after
Rake.application.instance_variable_set(:@top_level_tasks, current_tasks)

Outputs:

$ rake test1
test1
after

$ rake test1 test2
test1
test2
after


Apart from the ugly Rake.application.instance_variable_set, you can enhance the last task on the command-line like so:

  last_task = Rake.application.top_level_tasks.last
  Rake::Task[last_task].enhance do
    puts 'after'
  end

That should do exactly what you need to do!


You could use the Kernel.trap call and attach to the "Exit" signal. It will fire upon both normal and abnormal exit.

Put this early in your rakefile:

Kernel.trap("EXIT") do
  Rake::Task[:final].invoke
end

Now any time you make a "final" task it will be executed at the very end of the program. no matter what.

task :final do
  puts "Hit return to continue..."
  STDIN.getc
end


I don't know if it's the best way but it's the simpler:

Make all your "public tasks" Summary ones that call real tasks.

task :compile => :realcompile do
   summary stuff
end


If anyone came here looking for how to run a task before all other tasks (eg, a special env loading task), you can still use the same enhance method, except only the first arguement:

task :environment do
  env = (ENV['RACK_ENV'] || 'production').downcase
  # do things before other tasks
end

# run environment task before all tasks for setup
Rake::Task.tasks.each do |t|
  next if t.name == 'environment'
  t.enhance [:environment]
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜