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

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

Related

How to get new release path in Capistrano 3?

Trying to use Capistrano 3 to deploy a project and have run into an issue. In one of my tasks I'm trying to change directories and then run composer install.
For the life of me I can't get it to cd into the proper folder.
Right now if I do
set :theme_path, "#{release_path}/web/app/themes/sage"
append :linked_dirs, "web/app/uploads"
append :linked_files, ".env"
set :keep_releases, 3
namespace :deploy do
desc "Build"
after :updated, :build do
on roles(:app) do
within release_path do
execute :composer, "install --no-dev --quiet"
execute :cd, "#{fetch(:theme_path)}; composer install --no-dev --quiet"
end
end
end
end
It's for some reason running it in the previous release. Doing a pwd instead of the composer install shows that it is inside /current/ and not in the new /release/ directory. So it runs my composer install in current, and then does all the symlinking, so I end up with it always running composer in the previous deploy, so my current deploy never works.
So if release_path is /current/ and not the release currently being deployed... how do I get that path? Or how should I go about running composer install in two places?
The within syntax is how you tell Capistrano where to execute a command. I am not sure why this isn't working for you. I've copied and pasted your example into one of my apps at it works fine:
namespace :deploy do
after :updated, :build do
on roles(:app) do
within release_path do
puts capture("pwd")
end
end
end
end
When I run cap production deploy I see the pwd I expect in the output:
/home/deployer/apps/[REDACTED]/releases/20180405162938
You definitely should not be using execute :cd. Use within instead. So for example, if you need to do two executions, one in release_path and another in :theme_path, then I would do the following:
within release_path do
execute :composer, "install --no-dev --quiet"
end
within fetch(:theme_path) do
execute :composer, "install --no-dev --quiet"
end

How to run a capistrano task within a whenever task?

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.

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 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