Set Default Stage with Capistrano 3

Set default stage with Capistrano 3

Capistrano v3 is somewhat of a wrapper around Rake, so you need to realize that what's really happening is that a production task is getting run first, followed by a deploy task.

If you debug it a little, you'll find that deploy.rb doesn't get loaded when you don't type in a stage. This is because the stage's task is where deploy.rb gets loaded: Looking at lib/setup.rb, a task is defined for each stage. When run, the stage's task sets :stage, loads up the capistrano defaults, and then finally loads your deploy.rb file.

So, an easy trick would be to tell Capistrano to invoke the stage task every time you run cap by adding this to the end of your Capfile (not your deploy.rb):

Rake::Task[:production].invoke

or, using the invoke method from Capistrano's DSL:

invoke :production

This may have some unintended consequences if you actually do use multiple stages, but if you only ever use the production stage, it should work fine.

Another easy solution could be a simple shell alias, such as alias cap='cap production', but it might not work great if you have multiple projects with different stage names.

Capistrano 3 don't set rails_env and stage on deploy

OMG I had

rails_env development;

insteфd

rails_env staging;

in /etc/nginx/sites-enabled/default file

How can I place capistrano stages into a sub-directory?

I was able to override some Capistrano methods to get this to work. I wrote the following code at the top of my Capfile:

module Capistrano
module DSL
module Stages

def stages
names = Dir[stage_definitions].map { |f| "#{File.dirname(f)}/#{File.basename(f, ".rb")}".gsub("#{stage_config_path.to_s}/", '') }
assert_valid_stage_names(names)
names
end

# Override stage_definitions to include subfolders
def stage_definitions
stage_config_path.join("**/*.rb")
end
end
end
end

Explanation

By overriding the #stage_definitions method, I added **/ to that it would look for the .rb files in sub directories.

The next issue was that capistrano/setup.rb had this line of code:

load stage_config_path.join("#{stage}.rb")

That means I need stage to include the folder name. Then I overrode #stages so that the names variable would be an array of stages, including the subdirectory if any. Example:

config/
├── deploy/
│ ├── group_1/
| ├── ├── stage1.rb
│ ├── stage2.rb
│ ├── stage3.rb

Becomes:

['group_1/stage1', 'stage2', 'stage3']

That allows the Rake tasks to be created and load the files correctly!

$ cap group_1/stage1 deploy

How do you deploy to only one server with Capistrano v3?

As pointed out, in Capistrano 3 the way to deploy specific parts of your app to a single server is making use of HOST filtering. Let’s imagine that you are deploying directly to production and you have this configuration in config/deploy/production.rb

set :stage, :production

server "webserver1.example.com”, roles: [:web]

server "appserver1.example.com", roles: [:app]
server "appserver2.example.com", roles: [:app]
server "appserver3.example.com", roles: [:app]

server “dbserver1.example.com”, roles: [:db]
server “dbserver2.example.com”, roles: [:db]


Then if you want to deploy only to your webserver1, you just run the command:

cap --hosts=webserver1.example.com production deploy

How to add an if staging check to Capistrano task?

fetch(:stage) is likely a symbol (it's been a while since I used capistrano). To verify this, use a more precise string representation:

execute "echo #{fetch(:stage).inspect}"

I'm betting it will print :staging. In which case you need to do

if fetch(:stage) == :staging


Related Topics



Leave a reply



Submit