tl;dr: to install a Vagrant plugin locally before publishing it to Rubygems, use bundle cache
and create a local rubygems index.
I have just bumped into a weird problem: I’m creating an Omnibus package, and I want to run builders for different systems with Vagrant. That’s supported and should run out of the box; but life would be too easy if it worked that way. There were some Gem updates, some dependency mess I’m too lazy to untangle, and as I tried to start vagrant up
, I ran into an obscure backtrace (and I wasn’t the only person that saw this error). Seems like a new problem, and there’s already an issue open for it on vagrant-berkshelf project.
Upgrade to Berkshelf 2.0. With a bit of luck, it should be a one-liner. Clone, bundle
, run tests; upgrade Berkshelf in .gemspec
, bundle
, run tests. They pass. Nice. Let’s try with my installed Vagrant… now, how do I install the patched plugin?
Oh, well. According to Vagrant docs, *the* supported way to install plugins is by publishing them on Rubygems. I don’t want to publish it yet, I’ve just created an untested patch!
The vagrant plugin install
command can accept file name. I suppose the file should be a built gem (the documentation doesn’t mention that), so let’s try. Sweet, now it fails to fetch the gem’s dependencies.
There also is a --plugin-source PLUGIN_SOURCE
option, documented as Add a RubyGems repository source. If I generate a rubygems index for my single gem, it still fails to find dependencies. Looks like it rather means Use specified RubyGems repository source. I need all dependencies in place, together with my built gem. Bundler had such an option, I think…
Solution!
- Build a
.gem
file with your plugin (for vagrant-berkshelf, it wasthor gem:build
). - Run
bundle cache
to have all dependencies as.gem
files invendor/cache
directory. - Copy built
pkg/vagrant-berkshelf-1.2.0.gem
gem tovendor/cache
cd vendor/cache
- Build a RubyGems repository index:
gem generate_index
- Install the plugin out of local RubyGems repository:
/usr/bin/vagrant plugin install vagrant-berkshelf --plugin-source file://
pwd
I needed to run /usr/bin/vagrant
explicitly, because I let Bundler install Vagrant as a local Ruby gem and put it in my path before system-wide Vagrant. If you do bundle install --path=somewhere/else
(I usually go with vendor/gems
), you won’t need to do this.
I hope this will save someone else an hour or two of their life, or even a gray hair – maybe it will be myself a month from now, trying to remember what was the magic there!