How to write a Bundler plugin
What is a plugin?
Why would I use a plugin?
Currently, a plugin is able to:
-
Add commands to Bundler (e.g.
bundle my_command
) - Add a special handler to install a gem (e.g. Mercurial or SVN)
-
Add functionality to specific hook points:
- A list of all available hooks, their descriptions, and their block arguments are available in the plugin/events.rb file.
-
Note: Make sure to check out the
events.rb
file in the version of Bundler you are using.
Using a plugin
Install a plugin from a command
Plugins can be installed from RubyGems (default) or from a Git server. To use a gem on your machine, you can run bundler plugin install
. Once the plugin is installed, the commands will be available for use and the hooks will be automatically registered with Bundler.
Run bundler plugin help install
for more details help and instructions on installing from Git.
Install a plugin from your Gemfile
You can also specify a plugin in your Gemfile:
plugin 'my_plugin' # Installs from Rubygems
plugin 'my_plugin', path: '/path/to/plugin' # Installs from a path
plugin 'my_plugin', git: 'https://github.com:repo/my_plugin.git' # Installs from Git
Getting started with development
1. Create a gem
You'll first need to create a specialized gem before you can make a Bundler plugin.
Create a gem using this guide. When you're done, come back to this guide and move onto step two.
2. Create a plugins.rb file
A plugins.rb
file is located at the top level of your gem's folder and is the entry point Bundler will use to call your plugin. This is a Ruby file that defines your commands, hooks, and other code. Often, you may just require the gem's upper-most lib file.
For example, if your gem is called "my_plugin", you might have a file at lib/my_plugin.rb
which contains the highest level namespace for your gem. Your plugins.rb
file might be:
require 'my_plugin'
The lib/my_plugin.rb
file would include other require statements, hooks, and commands similar to a normal gem.
3. Making Bundler commands
Bundler commands allow you to extend the Bundler interface with additional functionality.
To add a Bundler command, you need to make a class that registers itself (or another class) as a command. For example, to add support for a bundler my_command
command, you might create a class like so:
class MyCommand < Bundler::Plugin::API
# Register this class as a handler for the `my_command` command
command "my_command"
# The exec method will be called with the `command` and the `args`.
# This is where you should handle all logic and functionality
def exec(command, args)
puts "You called " + command + " with args: " + args.inspect
end
end
module MyCommand
# Register this class as a handler for the `my_command` command
Bundler::Plugin::API.command('my_command', self)
# The exec method will be called with the `command_name` and the `args`.
# This is where you should handle all logic and functionality
def exec(command_name, args)
puts "You called " + command_name + " with args: " + args.inspect
end
end
These two elements are important in order for a command to register in Bundler:
-
Bundler::Plugin::API.command(COMMAND_NAME, CLASS)
orcommand 'COMMAND_NAME'
is called, depending on the method used (see examples above) -
The class defines the instance method
exec(command_name, args)
4. Using Bundler hooks
To interface with various parts of Bundler, you can use a hook. Hooks will let you inject some functionality at specific events by registering to listen for specific things to happen. To listen to an event, you need to add a hook for it and provide a block.
For example, for a Bundler::Plugin::Events::GEM_BEFORE_INSTALL_ALL
hook you must give a block that has an argument for an Array of Bundler::Dependency
objects:
Bundler::Plugin.add_hook('before-install-all') do |dependencies|
# Do something with the dependencies
end
5. Developing a source plugin
A source plugin allows you to specify more possible installation sources to use within Bundler. For example, let's say you want to install gems from Amazon S3. This can be done by building a plugin.
It is recommended to get familiar with the API for Bundler::Plugin::API::Source
which is available
on rubydoc.info
or
in the source code.
The basic overview of the source plugin is that you must subclass Bundler::Plugin::API::Source
and override a number of methods. Those methods are indicated in the docs/source code linked above.
Bundler uses the source plugin API to provide interfaces for RubyGems, Git, and path-based gems. The source code for these pieces may prove useful in understanding the API:
6. Running your plugin locally
To install and run your plugin locally, you can run bundler plugin install copycat --source file://PATH_TO_GEM
7. Deploying your plugin
Deploy your plugin to RubyGems so others can install it. For instructions on deploying to RubyGems, visit this guide.
Although plugins can be installed from a git branch, it's recommended to install plugins directly from RubyGems.
Example Plugins
- For a plugin that adds a command, take a look at kddeisz/bundler-console
- For a plugin that makes use of hooks, take a look at jules2689/extended_bundler-errors
- For an example of source plugin, take a look at Bundler's implementations for the RubyGems source, the git source, and the path source