Can I pass a multiline argument to rake task? (Not using ENV vars) - rake

Both
rake some:task["aaa
bbb
ccc"]
and
rake some:task["aaa\nbbb\nccc"]
fail.
Dose Rake accept multiline arguments in the first place?

Do it like this :
require 'rake'
task :taskname, [:argument1, :argument2] do |t, args|
puts "Args are: #{args}"
end
In command line:
> rake taskname[1,2]
Args are: {:argument1=>"1", :argument2=>"2"}

I looked up the code and found that it's impossible to send multi "line" params to rake command.
https://github.com/ruby/rake/blob/86af0ef6d793b85068a44fb3407b23c9c9b09bc7/lib/rake/application.rb#L154
/^some_patterns$/ =~ string.to_s
It looks like a rake command is supposed to be a single line.

Related

Capistrano 3: How can I suppress status output?

I've created a Capistrano task to execute a rake command. I plan to redirect the output (STDOUT) to a file. E.g.
cap production invoke:rake TASK=mytask > out
This works, but my output includes some additional Capistrano status output, e.g.
00:00 invoke:rake
01 $HOME/.rbenv/bin/rbenv exec bundle exec rake mytask
...
✔ 01 ubuntu#mydomain.com 11.399s
Is there any way to suppress this?
It's probably stderr output. If so, you can redirect standard error to standard out like so:
cap production invoke:rake TASK=mytask > out 2>&1
Okay, so I think I figured out a pretty good solution.
The key was to use capture (not documented in Capistrano 3.x, but still works).
https://github.com/capistrano/capistrano-2.x-docs/blob/master/2.x-DSL-Action-Inspection-Capture.md
namespace :invoke do
desc "Execute a rake task on a remote server"
task :rake do
if ENV['TASK']
on roles(:app) do
with rails_env: fetch(:rails_env) do
puts capture :rake, ENV['TASK']
end
end
else
puts "\n\nFailed! You need to specify the 'TASK' parameter!",
"Usage: cap <stage> invoke:rake TASK=your:task"
end
end
end

How to get the final command to be executed by sshkit

I want to create a gem that has de ability to take a task and wrap all commands in another command.
For example, the capistrano3-unicorn gem unicorn:start task will execute on the server something like bundle exec unicorn -c unicorn.rb -E production, but the execute method is wrapped by a within method, so the command to be executed on the server will be something like cd /home/deploy/application/myapp/current && bundle exec unicorn -c unicorn.rb -E production
I want to be able to create a rake task that takes that unicorn:start task and wrap it inside another task.
For example if I want to create an upstart config file for the app, I could adds this command to a upstart.conf template and the run service my-unicorn-app start
That would be a use case I'm trying to pursue.
In SSHKit formatters the write command is called with a command arg that have what I'm looking for. But I need this at capistrano task level.
Thanks
I think what you're asking is how to access the exact command that is sent via SSH. What you're looking for is the #command method, on the return value of which you can call #to_command. Since #command is a private method, we need to use #send.
namespace :unicorn
task :set_restart_command do
on(roles(:web)) do
within release_path do
set(:unicorn_start_command,
send(:command, :unicorn, "-c unicorn.rb -E production").to_command)
end
end
end
end
Now, in another task, you can use fetch(:unicorn_start_command)

Delayed_job + sitemap:refresh

So im trying to get delayed_jobs to run my sitemap:refresh command from the sitemap gem. Not sure why its not showing up in my local rake jobs:work. If i run sitemap:refresh in the terminal it runs fine and delayed_jobs runs all my other rake tasks.
in sitemap_refresh.rb
require 'sitemap_generator/tasks'
require 'delayed_job'
require 'delayed/tasks'
module Sitemap
class Refresh
def perform
`rake sitemap:refresh`
end
end
end
in my rakefile thats calling this:
task :sitemap => :environment do
load 'sitemap_refresh.rb'
puts "Refreshing Sitemap"
Delayed::Job.enqueue Sitemap::Refresh.new
puts "Sitemap has been refreshed"
end
Ive also tried replacing rake sitemap:refresh with system "sitemap:refresh" both appear to work just not in my worker from rake jobs:work.
solved the problem turns out for just needed to replace rake sitemap:refresh with Rake::Task["sitemap:refresh"].execute

How can I call a rake task on a git submodule?

I have a project including a number of vendored javascripts, e.g. jQuery. I'm including these scripts as git submodules. However, for my build process, I need the built script, not the whole repository of that script. So I'm trying to set up a rake task to build each script - preferably using the script's own rakefile - and then copy the built script into my asset directory.
file "app/vendor/scriptname.js" do
# Call the task that builds the script here
sh "cp app/vendor/script-submodule/dist/scriptname.js app/vendor/"
end
desc "Make vendor scripts available for build"
task :vendor => "app/vendor/scriptname.js" do
end
If I use import 'app/vendor/scriptname/Rakefile' in my Rakefile, I should have access to the rake task that builds the script, right? How would I call it? Or should I just use sh "cd app/vendor/script-submodule/ && rake dist" and call it good?
I'm working out a similar problem and it would seem to work just fine by calling the rake task as you normally would. Here's what my example looks like, see if you can get yours to fit.
# Rakefile
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
load 'engines/foo_engine/Rakefile'
MyApp::Application.load_tasks
Then in my submodule's Rakefile:
# engines/foo_engine/Rakefile
Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each do |f|
load f
end
And a sample rake task:
# engines/foo_engine/lib/tasks/foo/bar/task.rake
namespace :foo do
namespace :bar do
desc "FooBar task"
task :foo_bar => :environment do
# perform task
end
end
end
Then from the command prompt:
rake foo:bar:task

How to profile Rake task?

I need to profile the rake task. Cause I'm noob I know only how to profile .rb code
like this: ruby -Ilib -S ruby-prof -p graph_html profile.rb > profile.html
But how do I profile a specific Rake task?
Rake is just a Ruby script, so you should be able to just call ruby-prof against rake, in the same way you'd profile any other script.
Given your invocation of ruby-prof, try:
ruby -Ilib -S ruby-prof -p graph_html `which rake` TASK > profile.html
I've just used the following command line:
ruby-prof -p graph_html /usr/local/bin/rake19 import_from_aws file=~/sourcedata batch=test1 > /tmp/profile.html
To profile an invocation of:
rake19 import_from_aws file=~/sourcedata batch=test1
If you want 'coarse' profiling and want to find out which task is the bottleneck, I suggest Mike William's excellent piece of code from here. It worked beautifully when I was profiling my Rake tasks.
module Rake
class Task
def execute_with_timestamps(*args)
start = Time.now
execute_without_timestamps(*args)
execution_time_in_seconds = Time.now - start
printf("** %s took %.1f seconds\n", name, execution_time_in_seconds)
end
alias :execute_without_timestamps :execute
alias :execute :execute_with_timestamps
end
end
I think it's worth mentioning that you might want to profile it using bundle instead of rake directly if you happen to be using bundler.
ruby-prof -p graph_html `which bundle` -- 'exec' 'rake' '-T' > profile.html