How to run a capistrano task within a whenever task? - capistrano

I have whenever gem setup properly. How can I run that capistrano from my whenever schedule.rb?
my schedule.rb
every 1.minute, roles: [:app] do
# how to run here a capistrano task
# invoke 'my_app:test'
end
My capistrano task:
namespace :my_app do
desc 'test'
task :test do
on roles(:web) do
puts "the task runs"
end
end
end
Or should I move that task into a rake task. And should I run that rake task within whenever and capistrano?

Jan, you may find documentation very useful https://github.com/javan/whenever. The code example below - I just copied and edited it from the doc.
schedule.rb
# run this task only on servers with the :app role in Capistrano
# see Capistrano roles section below
every :day, at: '12:20am', roles: [:web] do
rake "app_server:task"
end
lib/tasks/test_task.rb
namespace :my_app do
desc 'test'
task :test do
puts "the task runs"
end
end
I believe it's easier to create Rake task and run it via Whenever. You can choose the Role, so basically you don't need to use Capistrano task (I believe you want to use it just because of Role).

I'd suggest your latter option, moving the logic to a rake task and executing it from both whenever and Capistrano. It'll be vastly easier and cleaner to do.

Related

What does deploy:initial do in Capistrano task

I use Capistrano for deploy. My Capistrano tasks are almost quoted from many blogs. I often find following structure.
namespace :deploy do
desc 'Say something before Deploy'
task :initial do
on roles(:app) do
before 'deploy:hoge', 'deploy:bazz'
invoke 'deploy'
end
end
task :hoge do
on roles(:app) do
puts "'hello, world'"
end
end
task :bazz do
on roles(:app) do
puts "'goodnight, world'"
end
end
end
What does before 'deploy:hoge', 'deploy:bazz' do in task statement? It doesn't display any messages. I think before statement must be outside of task statement.
In Capistrano 3.x at least, there is no such thing as a built-in deploy:initial task. Declaring a task with that name does not do anything special.
I think before statement must be outside of task statement.
You are exactly right. Any before and after declarations should be done at the top level and never within a task block.
As it stands, the example that you gave does nothing. If you want to run a certain task before deploy begins, you would hook into the deploy:starting task, like this:
before "deploy:starting", "deploy:hoge"
Furthermore, there is nothing special about the deploy namespace. I recommend declaring your own custom tasks in a different namespace, to keep them visually separated. Then you can easily distinguish between a built-in Capistrano task and your custom ones.
So I would rewrite the example like this:
namespace :myapp do
task :hoge do
on roles(:app) do
puts "'hello, world'"
end
end
task :bazz do
on roles(:app) do
puts "'goodnight, world'"
end
end
end
# Invoke hoge and bazz before deployment begins
before "deploy:starting", "myapp:hoge"
before "deploy:starting", "myapp:bazz"
The full list of built-in Capistrano task that you can use with before and after can be found here:
http://capistranorb.com/documentation/getting-started/flow/

Capistrano before hook for all tasks

I want to run a function before any Capistrano v2.X task is invoked in the deploy namespace.
I have the following which works for a specific task, but how do I hook for all tasks in the namespace, not just a particular task?
before "deploy:justin" do
puts "in before hook"
my_funnction_here
end
namespace :deploy do
task :justin do
puts "in task justin"
end
end
There are some built in points in Capistrano's deployment flow that you can hook into.
For example you can do:
before 'deploy:starting', :some_task do
# Your code here
end
See http://capistranorb.com/documentation/getting-started/flow/ for the list.
I think with that and a little reshuffling of your current code you can make it work. Hope that helps.

Run local executable file on remote servers with Capistrano

I have a pretty long .sh file in my Capistrano tools directory that is intended to be executed on servers, not locally. Is there a simple way to execute this file on servers inside a Capistrano task without manually copying it on each server?
Assuming that the script is in your repository, you can create a custom task which allows you to do exactly that. Something like:
namespace :deploy do
desc 'Run custom command'
task :run_custom_command do
on roles(:app) do
# Your restart mechanism here, for example:
execute release_path.join('tools/command.sh')
end
end
before :publishing, :run_custom_command
end

How to pass arguments to Capistrano 3 tasks in deploy.rb

Here is an tutorial how to pass parameters to an capistrano 3 task.
namespace :task do
desc 'Execute the specific cmd task'
task :invoke, :command do |task, args|
on roles(:app) do
execute :cmd, args[:command]
end
end
end
Can executed with:
$ cap staging "task:invoke[arg]"
How can i use this in my deploy.rb? The following does not work.
before :started, "task:invoke[arg]"
Not sure about before/after, but with Capistrano 3 you can always use the rake syntax and call task from within another task:
Rake::Task["mynamespace:mytask"].invoke(arg)
You can use invoke method:
before :started, :second_param do
invoke 'task:invoke', 'arg'
end
Also one thing which might be helpful, capistrano and rake allowing to execute task only first time, this might be common issue for task with parameters, cause you may reuse it with different value. To allow doing it you need to re-enable the task:
namespace :task do
desc 'Execute the specific cmd task'
task :invoke, :command do |task, args|
on roles(:app) do
execute :cmd, args[:command]
task.reenable # <--------- this how to re-enable it
end
end
end

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