railsware / capistrano-multiconfig

Capistrano extension that allows to use multiple configurations
MIT License
65 stars 18 forks source link

How to invoke cap tasks across projects (stages)? #12

Open richardkmichael opened 10 years ago

richardkmichael commented 10 years ago

Just a question:

I have projects foo and bar, each with production and staging stages and a deploy task.

I can invoke them on the command line as:

cap foo:production deploy
cap bar:production deploy

I want to write a top-level deploy task which invokes both foo and bar deploy, with usage: cap production deploy.

AFAICT, doing this programmatically in cap with multistage is difficult, because caphub overloads the stage itself; meaning, cap must execute a task in another stage.

I can do this with enhance(), to add a prerequisite:

# This "works"; invoked as "cap foo:production deploy".
Rake::Task['deploy'].enhance(['foo:production']).invoke

# Or with cap's DSL, invoke()
invoke Rake::Task['deploy'].enhance(['foo:production'])

But then, I need to clear the prerequisites (remove foo:production), reenable the task, and enhance again with bar:production.

Rake::Task['deploy'].clear_prerequisites
Rake::Task['deploy'].reenable
Rake::Task['deploy'].enhance(['bar:production']).invoke

# Repeat across projects...

Is there a "caphub" way to do this?

Thank you!

ayanko commented 10 years ago

Looks like you are not following capistrano philosophy.

capistrano-multiconfig is nested version of capistrano/stages. That it is also just regular task. And all tasks are always invoked in the given order:

cap task1 task2 ... taskN

Even if you create "hacked" task that will execute it in given order there is might be a risk that configuration of one task will impact on another one. It's not safe.

The only true way probably is create extra configuration like:

cap all:production deploy

It can use capistrano parallelism to deploy different codes to different hosts (if possible)

Otherwise just create bash script:

#!/bin/bash
cap foo:production deploy
cap bar:production deploy
richardkmichael commented 10 years ago

Indeed; it is exactly the all:production task that I am writing.

How do you propose that I invoke foo:production deploy then bar:production deploy from within all:production deploy? (Hrm.. are you suggesting to duplicate/copy-paste all the steps from foo:production and bar:production in all:production? That seems crazy.)

(Aside, shelling out to call cap again feels the most "unsafe" to me. Writing a "wrapper" script is annoying because it's then a special case and not used with cap.)

jcleary commented 9 years ago

What about creating the production task that shells out to the command line to call Capistrano multiple times in sequence. That way you don't run the risk of the tasks running into one another.

task :production do 
    run_locally do    
        execute(:cap, 'foo:production deploy')
        execute(:cap, 'bar:production deploy')
    end
end