komazarari / capistrano-locally

Capistrano plugin to simplify "localhost" deployment, without SSH-ing to localhost.
MIT License
74 stars 19 forks source link

Capistrano-locally with Capistrano Whenever - undefined method `roles_array' for SSHKit #2

Open OlivierGrimard opened 8 years ago

OlivierGrimard commented 8 years ago

Hi, I want to use Capistrano without SSH access. Capistrano-locally looks great but when I add plugin whenever, I have an error with the SSHKit.

Capfile: require "whenever/capistrano"

cap production deploy .... (Backtrace restricted to imported tasks) cap aborted! NoMethodError: undefined method `roles_array' for #SSHKit::Host:0x00000003760b30

Tasks: TOP => whenever:update_crontab (See full trace by running task with --trace) The deploy has failed with an error: undefined method `roles_array' for #SSHKit::Host:0x00000003760b30

Any idea why?

komazarari commented 8 years ago

Hello @OlivierGrimard , thanks for your reporting.

capistrano-locally eval a block with SSHKit::Backend::Local.new like capistrano's run_locally block and it's different from capistrano's on block which eval with Capistrano::Configuration::Server. So it cannot use roles and user-property in run_locally.

Very unfortunately, I have no idea expect for such a dirty monkey patch: :tired_face:

module SSHKit
  # https://github.com/capistrano/sshkit/blob/e06d6b8424979a6a3a2974f375490d2aa15c2ac4/lib/sshkit/backends/local.rb#L9-L12
  class Backend::Local
    def initialize(cap_server, &block)
      @host = SSHKit::Host.new(:local) # just for logging
      @block = block
      @host.properties[:server] = cap_server
    end
  end
  class Host
    extend Forwardable
    def_delegators :'properties[:server]', :roles_array
  end
end
MisterBowie commented 4 years ago

I have the same problem

MisterBowie commented 4 years ago

how to use them?

module SSHKit
  # https://github.com/capistrano/sshkit/blob/e06d6b8424979a6a3a2974f375490d2aa15c2ac4/lib/sshkit/backends/local.rb#L9-L12
  class Backend::Local
    def initialize(cap_server, &block)
      @host = SSHKit::Host.new(:local) # just for logging
      @block = block
      @host.properties[:server] = cap_server
    end
  end
  class Host
    extend Forwardable
    def_delegators :'properties[:server]', :roles_array
  end
end

thanks

MisterBowie commented 4 years ago

I used the whenever, I can use it after deleting.

Murzic commented 4 years ago

Hello, here's a way to apply the monkey-patch provided by @komazarari

Split it into two parts: lib/gem_extensions/sshkit/backend/local.rb

module GemExtensions
  module SSHKit
    module Backend
      module Local
        def self.included(base)
          base.class_eval do
            define_method(:initialize) do |*args, &block|
              @host = ::SSHKit::Host.new(:local) # just for logging
              @block = block
              @host.properties[:server] = args.first
            end
          end
        end
      end
    end
  end
end

and lib/gem_extensions/sshkit/host.rb

module GemExtensions
  module SSHKit
    module Host
      def self.included(base)
        base.class_eval do
          base.extend Forwardable
          base.def_delegators :'properties[:server]', :roles_array
        end
      end
    end
  end
end

Another file will apply the patches to the SSHKit library. lib/gem_extensions/sshkit.rb

if defined?(SSHKit)
  require_relative 'sshkit/backend/local'
  require_relative 'sshkit/host'
  SSHKit::Backend::Local.include GemExtensions::SSHKit::Backend::Local
  SSHKit::Host.include GemExtensions::SSHKit::Host
end

Now, in Capfile, require the last file after the require 'capistrano/locally' line, like so:

...
require 'capistrano/locally'
require_relative 'lib/gem_extensions/sshkit'
...

The line require_relative 'lib/gem_extensions/sshkit' should be removed from Capistrano when deploying the "normal" capistrano way(not locally). Also, make sure that the "monkey-patch" files are not auto-loaded by Rails, if you use Rails.

This was tested for the following combination of gem versions: rails (4.2.11), capistrano (3.4.0), sshkit (1.17.0), capistrano-locally (0.2.6) and whenever (0.9.7)