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

Make all SCMs inherit from SCM::Plugin

This makes it much easier (no hacks needed) to determine whether the
user has installed an SCM plugin: simply check that the plugin responds
to `scm?` and that it returns true. A new SCM::Plugin base class makes
it easy to write such a plugin.

This commit also updates the website docs that explain how to write SCM
plugins so that they refer to this new technique.
This commit is contained in:
Matt Brictson 2016-10-23 21:13:19 -07:00
parent ff686ef802
commit e6ddd93ece
No known key found for this signature in database
GPG key ID: 2F279EAD1F2ACFAF
9 changed files with 46 additions and 26 deletions

View file

@ -20,20 +20,20 @@ Capistrano checks out your application's source code. SCM plugins can be
packaged as Ruby gems and distributed to other users.
This document is a short guide to writing your own plugin. *It applies to
Capistrano 3.5.0 and newer.*
Capistrano 3.7.0 and newer.*
### 1. Write a Ruby class that extends Capistrano::Plugin
### 1. Write a Ruby class that extends Capistrano::SCM::Plugin
Let's say you want to create a "Foo" SCM. You'll need to write a plugin class,
like this:
```ruby
require "capistrano/plugin"
require "capistrano/scm/plugin"
# By convention, Capistrano plugins are placed in the
# Capistrano namespace. This is completely optional.
module Capistrano
class FooPlugin < ::Capistrano::Plugin
class FooPlugin < ::Capistrano::SCM::Plugin
def set_defaults
# Define any variables needed to configure the plugin.
# set_if_empty :myvar, "my-default-value"
@ -42,11 +42,13 @@ module Capistrano
end
```
### 2. Implement the create_release task
### 2. Implement a create_release task
When the user runs `cap deploy`, your SCM is responsible for creating the
release directory and copying the application source code into it. You need to
do this using a `create_release` task that is namespaced to your plugin.
do this using a task that is registered to run after `deploy:new_release_path`.
By convention (not a requirement), this task is called `create_release`.
Inside your plugin class, use the `define_tasks` and `register_hooks` methods
like this:
@ -56,7 +58,6 @@ def define_tasks
# The namespace can be whatever you want, but its best
# to choose a name that matches your plugin name.
namespace :foo do
# The task *must* be named `create_release`
task :create_release do
# Your code to create the release directory and copy
# the source code into it goes here.

View file

@ -140,6 +140,10 @@ module Capistrano
load_immediately: load_immediately)
end
def scm_plugin_installed?
installer.scm_installed?
end
def servers
@servers ||= Servers.new
end

View file

@ -26,6 +26,7 @@ module Capistrano
plugin.define_tasks
plugin.register_hooks if load_hooks
@scm_installed ||= provides_scm?(plugin)
if load_immediately
plugin.set_defaults
@ -35,6 +36,16 @@ module Capistrano
end
end
end
def scm_installed?
@scm_installed
end
private
def provides_scm?(plugin)
plugin.respond_to?(:scm?) && plugin.scm?
end
end
end
end

View file

@ -29,7 +29,8 @@ module Capistrano
set(:scm, :git) if using_default_scm?
print_deprecation_warnings_if_applicable
return if scm_plugin_loaded?
# Note that `scm_plugin_installed?` comes from Capistrano::DSL
return if scm_plugin_installed?
if built_in_scm_name?
load_built_in_scm
@ -47,13 +48,6 @@ module Capistrano
@using_default_scm = (fetch(:scm) == DEFAULT_GIT)
end
# This is somewhat of a hack, because there is no guarantee that a third-
# party SCM will necessarily implement the typical SCM tasks. But it works
# well enough for the built-in SCMs.
def scm_plugin_loaded?
Rake::Task.tasks.any? { |t| t.name =~ /^[^:]+:create_release/ }
end
def scm_name
fetch(:scm)
end
@ -102,7 +96,7 @@ module Capistrano
def print_deprecation_warnings_if_applicable
if using_default_scm?
warn_add_git_to_capfile unless scm_plugin_loaded?
warn_add_git_to_capfile unless scm_plugin_installed?
elsif built_in_scm_name?
warn_set_scm_is_deprecated
elsif third_party_scm_name?

View file

@ -8,7 +8,7 @@ module Capistrano
:configure_backend, :fetch, :set, :set_if_empty, :delete,
:ask, :role, :server, :primary, :validate, :append,
:remove, :dry_run?, :install_plugin, :any?, :is_question?,
:configure_scm
:configure_scm, :scm_plugin_installed?
def roles(*names)
env.roles_for(names.flatten)

View file

@ -1,7 +1,6 @@
require "capistrano/plugin"
require "capistrano/scm"
require "capistrano/scm/plugin"
class Capistrano::SCM::Git < Capistrano::Plugin
class Capistrano::SCM::Git < Capistrano::SCM::Plugin
def set_defaults
set_if_empty :git_shallow_clone, false
set_if_empty :git_wrapper_path, lambda {

View file

@ -1,7 +1,6 @@
require "capistrano/plugin"
require "capistrano/scm"
require "capistrano/scm/plugin"
class Capistrano::SCM::Hg < Capistrano::Plugin
class Capistrano::SCM::Hg < Capistrano::SCM::Plugin
def register_hooks
after "deploy:new_release_path", "hg:create_release"
before "deploy:check", "hg:check"

View file

@ -0,0 +1,13 @@
require "capistrano/plugin"
require "capistrano/scm"
# Base class for all built-in and third-party SCM plugins. Notice that this
# class doesn't really do anything other than provide an `scm?` predicate. This
# tells Capistrano that the plugin provides SCM functionality. All other plugin
# features are inherited from Capistrano::Plugin.
#
class Capistrano::SCM::Plugin < Capistrano::Plugin
def scm?
true
end
end

View file

@ -1,7 +1,6 @@
require "capistrano/plugin"
require "capistrano/scm"
require "capistrano/scm/plugin"
class Capistrano::SCM::Svn < Capistrano::Plugin
class Capistrano::SCM::Svn < Capistrano::SCM::Plugin
def register_hooks
after "deploy:new_release_path", "svn:create_release"
before "deploy:check", "svn:check"