Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command mapping #56

Open
pmeinhardt opened this issue Feb 8, 2019 · 3 comments
Open

Command mapping #56

pmeinhardt opened this issue Feb 8, 2019 · 3 comments

Comments

@pmeinhardt
Copy link

Hey there, thanks for creating this gem 🙇

I've run into an issue when following the instructions in the README as the shared_path is not necessarily set correctly when you define the command mapping in the top-level scope.

Instead, what worked for me was to defer the mapping until after deploy:starting, where we can be sure the shared_path is initialized to the correct value:

namespace :deploy do
  # Add command mappings
  after :starting, :map_commands do
    SSHKit.config.command_map[:composer] = "php #{shared_path.join('composer.phar')}"
  end

  # Install composer (https://getcomposer.org/)
  after :starting, 'composer:install_executable'

  # …
end

Maybe it'd make sense to update the README and composer:install_executable task description?

@pmeinhardt
Copy link
Author

pmeinhardt commented Feb 10, 2019

Mmh 🤔 Setting up the mapping after deploy:starting wasn't such a great idea. This means that the command will only work properly when you run a deploy:* task that also invokes deploy:starting (I should've seen that).

However, as mentioned before, setting up the mapping in the top scope in config/deploy.rb breaks for me, as I am using a different :deploy_to path per stage, e.g.

# config/deploy/staging.rb
set :deploy_to, '/var/www/app-staging'
# config/deploy/production.rb
set :deploy_to, '/var/www/app-production'

When I set up the command mapping in config/deploy.rb, I get the following result:

set :application, 'app'
SSHKit.config.command_map[:composer] = "php #{shared_path.join('composer.phar')}"

Printing the mapping in a task (say maptest) and running cap staging maptest yields:

php /var/www/app/shared/composer.phar

It should be:

php /var/www/app-staging/shared/composer.phar

When I define the command mapping in the separate stage files (after the final, stage-specific :deploy_to value is set), everything works as expected. This totally makes sense 😁 That does mean however, that I need to duplicate the command mappings for every stage 😞

I'll probably find a cleaner solution though and post it here when I find it 🙂

Then maybe updating the instructions here could be worth it for people who run into a similar issue.

Cheers

@pmeinhardt
Copy link
Author

pmeinhardt commented Feb 10, 2019

Okay, so the following works for all my use-cases (running composer tasks during deploy but also separately):

# config/deploy.rb

stages.each do |stage|
  after stage, :map_commands do
    SSHKit.config.command_map[:composer] = "php #{shared_path.join('composer.phar')}"
  end
end

This defers the command mapping until all the stage variables, in particular :deploy_to, have been initialized with their final values.

Should this be mentioned in the description for the composer:install_executable task or what would be the best place for it?

I am also wondering whether this would be relevant for the general Capistrano FAQs or some place similar @capistrano?

In hindsight it makes a lot of sense, but initially I didn't think too much about the order in which the general deploy config, stage config and command mappings are initialized. I guess others might run into this too.

Thank you all for these super-helpful tools 🙇

@pmeinhardt
Copy link
Author

pmeinhardt commented Feb 10, 2019

An (more involved) alternative could also be for Capistrano to provide a complete wrapper around the SSHKit command map, which might look like the following:

# Define a command mapping with lazy initialization
command :composer, -> { "php #{shared_path.join('composer.phar'}" }

# Read command mappings
commands[:composer]
# => 'php /var/www/…'

Not sure about how exactly this could be tied into SSHKit though or whether that would just remain on the Capistrano layer:

task :example do
  on roles(:all) do
    execute commands[:composer], '--version'
    # or (as before)
    execute :composer, '--version'
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant