1
0
Fork 0
mirror of https://github.com/capistrano/capistrano synced 2023-03-27 23:21:18 -04:00

Move plugin installation logic out of initializer

Plugins are now installed via a `install_plugin` DSL method, rather than as a
side-effect of calling `new`. You may pass either the plugin class or the
instance of the class to `install_plugin`; both accomplish the same thing.

The logic for executing the plugin is now encapsulated in the following class:
`Capistrano::Configuration::PluginInstaller`.
This commit is contained in:
Matt Brictson 2016-02-27 14:47:18 -08:00
parent ec8ab0bc15
commit 20fa2219c3
5 changed files with 55 additions and 24 deletions

View file

@ -1,5 +1,6 @@
require_relative "configuration/filter"
require_relative "configuration/question"
require_relative "configuration/plugin_installer"
require_relative "configuration/server"
require_relative "configuration/servers"
@ -151,6 +152,10 @@ module Capistrano
fetch(:sshkit_backend) == SSHKit::Backend::Printer
end
def install_plugin(plugin, hooks:true)
installer.install(plugin, hooks: hooks)
end
private
def cmdline_filters
@ -169,6 +174,10 @@ module Capistrano
@validators ||= {}
end
def installer
@installer ||= PluginInstaller.new
end
def fetch_for(key, default, &block)
if block_given?
config.fetch(key, &block)

View file

@ -0,0 +1,33 @@
# Encapsulates the logic for installing plugins into Capistrano. Plugins must
# simply conform to a basic API; the PluginInstaller takes care of invoking the
# API at appropriate times.
#
# This class is not used directly; instead it is typically accessed via the
# `install_plugin` method of the Capistrano DSL.
#
module Capistrano
class Configuration
class PluginInstaller
# "Installs" a Plugin into Capistrano by loading its tasks, hooks, and
# defaults at the appropriate time. The hooks in particular can be
# skipped, if you want full control over when and how the plugin's tasks
# are executed. Simply pass `hooks:false` to opt out.
#
# The plugin class or instance may be provided. These are equivalent:
#
# install(Capistrano::SCM::Git)
# install(Capistrano::SCM::Git.new)
#
def install(plugin, hooks:true)
plugin = plugin.is_a?(Class) ? plugin.new : plugin
plugin.define_tasks
plugin.register_hooks if hooks
Rake::Task.define_task("load:defaults") do
plugin.set_defaults
end
end
end
end
end

View file

@ -6,7 +6,8 @@ module Capistrano
extend Forwardable
def_delegators :env,
:configure_backend, :fetch, :set, :set_if_empty, :delete,
:ask, :role, :server, :primary, :validate, :append, :remove, :dry_run?
:ask, :role, :server, :primary, :validate, :append,
:remove, :dry_run?, :install_plugin
def is_question?(key)
env.is_question?(key)

View file

@ -20,37 +20,21 @@ require "rake/tasklib"
#
# Package up and distribute your plugin class as a gem and you're good to go!
#
# To use a plugin, all a user has to do is instantiate it in the Capfile, like
# this:
# To use a plugin, all a user has to do is install it in the Capfile, like this:
#
# # Capfile
# require "capistrano/superfancy"
# Capistrano::Superfancy.new
# install_plugin Capistrano::Superfancy
#
# Or, to install the plugin without its hooks:
#
# # Capfile
# require "capistrano/superfancy"
# Capistrano::Superfancy.new(hooks: false)
# install_plugin Capistrano::Superfancy, hooks: false
#
class Capistrano::Plugin < Rake::TaskLib
include Capistrano::DSL
# Constructing a plugin "installs" it into Capistrano by loading its tasks,
# hooks, and defaults at the appropriate time. The hooks in particular can be
# skipped, if you want full control over when and how the plugin's tasks are
# executed. Simply pass `hooks:false` to opt out.
#
def initialize(hooks: true)
define_tasks
register_hooks if hooks
task "load:defaults" do
set_defaults
end
end
private
# Implemented by subclasses to provide default values for settings needed by
# this plugin. Typically done using the `set_if_empty` Capistrano DSL method.
#
@ -94,6 +78,8 @@ class Capistrano::Plugin < Rake::TaskLib
#
def define_tasks; end
private
# Read and eval a .rake file in such a way that `self` within the .rake file
# refers to this plugin instance. This gives the tasks in the file access to
# helper methods defined by the plugin.

View file

@ -42,33 +42,35 @@ module Capistrano
end
it "defines tasks when constructed" do
DummyPlugin.new
install_plugin(DummyPlugin)
expect(Rake::Task["hello"]).not_to be_nil
end
it "registers hooks when constructed" do
DummyPlugin.new
install_plugin(DummyPlugin)
expect(Rake::Task["deploy:published"].prerequisites).to include("hello")
end
it "skips registering hooks if :hooks => false" do
DummyPlugin.new(hooks: false)
install_plugin(DummyPlugin, hooks: false)
expect(Rake::Task["deploy:published"].prerequisites).to be_empty
end
it "doesn't call set_defaults immediately" do
dummy = DummyPlugin.new
install_plugin(dummy)
dummy.expects(:set_defaults).never
end
it "calls set_defaults during load:defaults" do
dummy = DummyPlugin.new
dummy.expects(:set_defaults).once
install_plugin(dummy)
Rake::Task["load:defaults"].invoke
end
it "is able to load tasks from a .rake file" do
ExternalTasksPlugin.new
install_plugin(ExternalTasksPlugin)
Rake::Task["plugin_test"].invoke
expect(fetch(:plugin_result)).to eq("hello")
end