Last active
August 29, 2015 14:03
-
-
Save sharplet/bb41ea90413f453b53b5 to your computer and use it in GitHub Desktop.
Normally a rake task won't complete if one of its prerequisites fails. Define a composite task to allow them all to run, capturing exceptions and reporting them only after all have completed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Take for example a convenience task, all_tests, that runs our app's | |
# test suite for multiple architectures: | |
# | |
# task :all_tests => [:test_64_bit, :test_32_bit] | |
# | |
# Defined as a regular task, Rake will bail out early if | |
# test_64_bit failed, never getting to the 32 bit tests. | |
# | |
# A composite task is almost identical in declaration: | |
# | |
# composite :all_tests => [:test_64_bit, :test_32_bit] | |
# | |
# This task will instead run *all* its prerequisites, recording if | |
# they fail, and only reporting failures once all tasks have completed. | |
# | |
class CompositeTask < Rake::Task | |
attr_reader :failures | |
# Hook into prerequisite invocation to add exception handling | |
# to each one. | |
def invoke_prerequisites(*args) | |
failures = [] | |
prerequisite_tasks.each do |p| | |
p.define_singleton_method(:execute) do |*args| | |
begin | |
super(*args) | |
failures << nil | |
rescue => e | |
failures << e | |
end | |
end | |
end | |
super(*args).tap { @failures = failures } | |
end | |
# When executing this task, see if any failures were reported | |
# and re-raise them. | |
def execute(*args) | |
super(*args) | |
failed_commands = prerequisite_tasks.zip(failures).delete_if { |_, failure| failure.nil? } | |
unless failed_commands.empty? | |
# TODO: work out how to re-raise more than just the first failure | |
raise failed_commands.map { |_, ex| ex }.first | |
end | |
end | |
end | |
def composite(*args, &block) | |
CompositeTask.define_task(*args, &block) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment