What Does the Term "Vendoring" or "To Vendor" Mean for Ruby on Rails

What does the term vendoring or to vendor mean for Ruby on Rails?

Vendoring is the moving of all 3rd party items such as plugins, gems and even rails into the /vendor directory.
This is one method for ensuring
that all files are deployed to the production server the same as the dev environment.

Best way to do this is either:

  rake gems:unpack

Or

  rake rails:freeze:gems

Use rake -T to see a full list of rake tasks.

What is vendoring?

Based on this answer

Defined here for Go as:

Vendoring is the act of making your own copy of the 3rd party packages
your project is using. Those copies are traditionally placed inside
each project and then saved in the project repository.

The context of this answer is in the Go language, but the concept still applies.

What does vendoring mean in Go?

Defined here for Go as:

Vendoring is the act of making your own copy of the 3rd party packages
your project is using. Those copies are traditionally placed inside
each project and then saved in the project repository.

I don't know squirt about Ruby.

Essentially you're taking a package, storing it within your own project and using that version to build from. I liken it to how you might have a "vendors" folder where you put third party css or js when building a web page.

What is the recommended way of vendoring rails for a production application?

I'd recommend freezing on a release:

rake rails:freeze:edge RELEASE=2.3.3

There is a git branch for 2-3-stable, but I've had a terrible time using it. Submodules are a bit of a pain. The tool Braid is pretty nice, but I like freezing Rails with releases.

Capistrano is going to be a little more sluggish deploying your code (the whole Rails codebase is in there), but capistrano itself and your production setup should not need to be altered.

Good luck!

Is it best-practice to commit the `vendor` directory?

The dep tool's FAQ answers this:

Should I commit my vendor directory?

It's up to you:

Pros

  • It's the only way to get truly reproducible builds, as it guards
    against upstream renames, deletes and commit history overwrites.
  • You don't need an extra dep ensure step to sync vendor/ with
    Gopkg.lock after most operations, such as go get, cloning, getting
    latest, merging, etc.

Cons

  • Your repo will be bigger, potentially a lot bigger, though prune can help minimize this problem.
  • PR diffs will include changes for files under vendor/ when Gopkg.lock is modified, however files in vendor/ are hidden by default on GitHub.

What is the purpose of vendor/bundle? Heroku tells me to remove it

If you have the vendor/bundle directory in your project then at some point you must have run the bundle command with the --path vendor/bundle argument. This will load the files for all your project's gems (listed in Gemfile) into the vendor/bundle directory 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 --path but 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 rubygems servers every time you run the bundle command.

bundle package takes it a step further and actually downloads the original gem files from rubygems and caches them into the vendor/cache directory. This means that you no longer need a connection to rubygems to 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 to rubygems to collect the new version the first time it is requested. Using bundle package will 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 bundle command every time you git push, reading your Gemfile.lock and installing the gems required for the application to work. By default the --path vendor/bundle option is used. This is so that each application has a set of gem files separate from all other apps on Heroku. If you have the vendor/bundle directory 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 into vendor/bundle directory which already exists. If it is pushed then Heroku removes the vendor/bundle directory before it runs bundle install to remove these potential conflicts. If this is the case then you will be wasting deploy time and bandwidth by leaving vendor/bundle under 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 package command and make sure that the vendor/cache directory is under source control. When Heroku runs bundle install it will use the contents of vendor/cache as the gem source rather than using rubygems. 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 using bundle package is 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/bundle to keep my local setup as close as possible to Heroku's. I put vendor/bundle into my project's .gitignore file, and I don't package gems, as my projects are updated relatively regularly.

Rails has a very limited .gitignore file. You are effectively expected to build up what you need yourself, which is why vendor/bundle is not included by default.

I assume that Heroku means bundle package when they say bundle pack.

Using vendored gems in vendor/cache with Docker

I managed to solve this. needed to edit the Dockerfile to copy gems at vendor/cache. Here is the modified gemfile which works and utilized docker caching

FROM ruby:2.6.6
WORKDIR /home/app/webapp
COPY Gemfile Gemfile.lock /home/app/webapp/
COPY vendor/cache /home/app/webapp/vendor/cache/
RUN bundle install
COPY . /home/app/webapp/
# Start the main process.
CMD ['/home/app/webapp/entrypoint.sh']

Adding the answer here, incase someone else get's the same error. Thank you for looking.



Related Topics



Leave a reply



Submit