Run rake tasks in sequence - ruby

I have rake tasks which i want to run in proper sequence.
I want to run one rake task which run other rake tasks in proper sequence.
How may i do that?

you should consider defining dependencies between your tasks like this
task :primary => [:secondary]
task :secondary do
puts "Doing Secondary Task"
end
But if you really, really need to call the tasks directly you can use invoke to call another task
task :primary do
Rake::Task[:secondary].invoke
end
task :secondary do
puts "Doing Secondary Task"
end
see also here

Related

Capistrano 2 - Pass array arguments to a Rake task

I am trying to write a Rake task in my deploy.rb that gets passed an array of arguments. I will run it through capistrano.
Assuming a task like the following:
desc "my task"
task :mytask, [:arguments] => :environment do |t, args|
puts 'hello'
end
When I try running cap mytask['arg1 arg2 arg3'], I get the following:
the task `mytask["arg1 arg2 arg3"]' does not exist
Any ideas? I have a task defined like this that I run locally with no problems, but defining tasks like this be run using cap does not work.
NOTE: running cap mytask without the arguments part works. This is obviously not what I want.
Rake tasks are defined by a string and called via Rake::Task["name"] internally . If cap treats your array as part of the task name string it will not work.
As 'mytask' != 'mytask["arg1 arg2 arg3"]'

Invoking the same rake task twice in RSpec

I am trying to test a rake task with rspec, and for that purpose I need to invoke it twice but
it is only being invoked once.
it 'first test' do
Rake::Task['my_rake_task'].invoke
# rake task was processed
end
it 'second test' do
Rake::Task['my_rake_task'].invoke
# rake task was NOT processed
end
if a rake task has already been invoked once it won't run again unless you call:
#rake[#task_name].reenable
or invoke it with
#rake[#task_name].execute
To adding to Guy Segev answer I prefer adding this to your spec file
after(:each) do
Rake::Task["task:name"].reenable
end

How can I have an rcov task know if a subtask failed?

I have this task:
task :all => ['foo', 'bar', 'announce_success']
If foo and bar don't raise exceptions, then announce_success happens. How can I have a particular task or code block execute if they do raise exceptions?
The way you have defined your tasks will cause rake to exit as soon as one of the dependencies fails/raises and exception. This is the core functionality of rake.
One way to work around though is to do something like
task :all do
task :tmp => ['foo','bar']
begin
Rake::Task[:tmp].invoke
rescue
#do something with the exception
end
end
Unfortunately that goes against the grain of Rake.
Ruby has an at_exit hook you can add a block of code to, if you want to run a bit of cleanup when Rake terminates. You can combine rake-tasks and at_exit hook like this:
task :cleanup do
at_exit {
# cleanup code here
}
end
Just make sure :cleanup is executed early in the list of dependencies.

Namespaces in Ruby Rake Tasks

Are the following equivalent?
namespace :resque do
task setup: :environment do
end
end
task "resque:setup" => :environment do
end
In short: yes. When running rake resque:setup both of these tasks will be invoked.
Rake will merge these tasks. You can test this by doing the following:
p Rake.application.tasks
Which in this case would return something like
[<Rake::Task resque:setup => [environment]>]
Which is simply an Array holding a single Rake::Task object. You can also check the scope or list of namespaces for a task by doing:
p Rake.application.tasks.first.scope
#=> ["resque"]
If you want to learn a little more on how the internals of Rake work, check out Rake::Task and Rake::TaskManager

Creating a Capistrano task that performs different tasks based on role

I'm looking for a way to call a single Capistrano task to perform different things to different roles. Is Capistrano able to do this, or do I have write a specific task for each role?
The standard way to do this in Capistrano:
task :whatever, :roles => [:x, :y, :z] do
x_tasks
y_tasks
z_tasks
end
task :x_tasks, :roles => :x do
#...
end
task :y_tasks, :roles => :y do
#...
end
task :z_tasks, :roles => :z do
#...
end
So yes, you do need to write separate tasks, but you can call them from a parent task and they will filter appropriately.
Actually no:
% cat capfile
server 'localhost', :role2
task :task1, :roles=>:role1 do
puts 'task1'
end
task :task2 do
task1
end
% cap task2
* executing `task2'
* executing `task1'
task1
The :roles param is passed further to run command etc but does not seem to affect whether the task is actually fired.
Sorry, didn't find the way to put a comment on comment so I've written it here.
You can also do
task :foo do
run "command", :roles => :some_role
upload "source", "destination", :roles => :another_role
end
Use namespacing:
https://github.com/leehambley/capistrano-handbook/blob/master/index.markdown#namespacing-tasks
namespace :backup do
task :default do
web
db
end
task :web, :roles => :web do
puts "Backing Up Web Server"
end
task :db, :roles => :db do
puts "Backing Up DB Server"
end
end
these tasks show up in a cap -T as
backup:default
backup:web
backup:db
There is a way, kind of. Check: http://weblog.rubyonrails.org/2006/8/30/capistrano-1-1-9-beta/ and you'll see that you can override the default roles using the ROLES environment variable.
I have a task defined as:
desc "A simple test to show we can ssh into all servers"
task :echo_hello, :roles => :test do
run "echo 'hello, world!'"
end
The :test role is assigned to one server.
On the command line, I can run:
[james#fluffyninja bin]$ cap echo_hello ROLES=lots_of_servers
And the task will now run on the lots_of_servers role.
I have not verified that this works inside a ruby script by updating the ENV hash, but this is a good start.
Only for the record, this could be a solution using Capistrano 3:
desc "Do something specific for 3 different servers with 3 different roles"
task :do_something do
on roles(:api_role), in: :sequence do
# do something in api server
end
on roles(:app_role), in: :sequence do
# do something in application server
end
on roles(:another_role), in: :sequence do
# do something in another server
end
end
The sever definition to perform "do_something" task in a application server would be something like:
server 'application.your.domain', user: 'deploy', roles: %w{app_role}
Then you can call the task (there are several ways to do it) and the task will execute specific instructions according to the "app_role".

Resources