Upon pushing some changes to Heroku, I noticed a warning about vendor/bundle (see WARNING below).
What is the purpose of this directory if, according to the warning, it should be “removed” from Git tracking?
Why isn’t vendor/bundle automatically .gitignore‘d by default by Rails?
Should I run bundle pack? (Is it actually bundle package??)
What are the pros and cons around bundle pack (relative to both development and production)?
To make this even more confusing, there’s a popular blog post, by Ryan McGeary, titled “Vendor Everything” Still Applies that strongly argues for running bundle install --path vendor and echo 'vendor/ruby' >> .gitignore and packaging gems in vendor/cache by running bundle package. Any light shed on this relative to my other concerns would be greatly appreciated.
Thank you.
-bash> git push production master
...
-----> Heroku receiving push
-----> Ruby/Rails app detected
-----> WARNING: Removing `vendor/bundle`.
Checking in `vendor/bundle` is not supported. Please remove this directory
and add it to your .gitignore. To vendor your gems with Bundler, use
`bundle pack` instead.
-----> Installing dependencies using Bundler version 1.2.1
Running: bundle install --without development:test --path vendor/bundle --binstubs bin/ --deployment
Using rake (0.9.2.2)
Using i18n (0.6.0)
...
If you have the
vendor/bundledirectory in your project then at some point you must have run thebundlecommand with the--path vendor/bundleargument. This will load the files for all your project’s gems (listed inGemfile) into thevendor/bundledirectory in your local project rather than to a system gem location. You would do this to completely isolate a project’s gems from any other project.Bundler is good at resolving all dependencies so it isn’t necessary to use the
--pathbut some people choose to do so as they wish to keep their gems separate and organised with their project. It also means that bundler on your local machine is set up the same way that Heroku uses bundler.With this option you are still downloading all gems from the
rubygemsservers every time you run thebundlecommand.bundle packagetakes it a step further and actually downloads the original gem files fromrubygemsand caches them into thevendor/cachedirectory. This means that you no longer need a connection torubygemsto run the bundle command as it will use the packaged files as the source. If you need to update a gem version then it will need to connect torubygemsto collect the new version the first time it is requested. Usingbundle packagewill of course require additional disc space which may or may not be an issue depending on the situation. It would also increase deploy time and bandwidth requirements every time you pushed to Heroku.Heroku runs the
bundlecommand every time yougit push, reading yourGemfile.lockand installing the gems required for the application to work. By default the--path vendor/bundleoption is used. This is so that each application has a set of gem files separate from all other apps on Heroku. If you have thevendor/bundledirectory in your source control and you push it to Heroku then you can see that there is the potential for significant conflict as it then attempts to load gems intovendor/bundledirectory which already exists. If it is pushed then Heroku removes thevendor/bundledirectory before it runsbundle installto remove these potential conflicts. If this is the case then you will be wasting deploy time and bandwidth by leavingvendor/bundleunder version control, it’s better to add it to your.gitignore.If you want complete control over your gems on Heroku then use the
bundle packagecommand and make sure that thevendor/cachedirectory is under source control. When Heroku runsbundle installit will use the contents ofvendor/cacheas the gem source rather than usingrubygems. Whether this is useful or not will be a matter of personal preference, the type of app that you are building and how often you update your gems. The Ryan McGeary post suggests that usingbundle packageis useful in case an old gem becomes unavailable at some point in the future. This would appear to be a bigger issue to projects/apps which are not regularly kept up to date.From my perspective, I generally use
--path vendor/bundleto keep my local setup as close as possible to Heroku’s. I putvendor/bundleinto my project’s.gitignorefile, and I don’t package gems, as my projects are updated relatively regularly.Rails has a very limited
.gitignorefile. You are effectively expected to build up what you need yourself, which is whyvendor/bundleis not included by default.I assume that Heroku means
bundle packagewhen they saybundle pack.