Check if Gemfile.lock matches Gemfile - ruby

I want to write a unit test to check if the Gemfile.lock in my project matches the Gemfile in case I forget to call bundle before committing.
Is there an option for the bundle command (or another method) to check this?
Note that bundle check does not suit this purpose. It checks to see if all gems in the Gemfile are installed on the local system, but it does not check the Gemfile.lock. Therefore the bundle install --deployment command on the server can fail even if bundle check succeeds on the development machine or in CI.

Try:
cp Gemfile.lock Gemfile.lock.orig
bundle install
diff Gemfile.lock Gemfile.lock.orig && echo "Gemfile.lock matches Gemfile"

Use bundle check command
Check searches the local machine for each of the gems requested in the
Gemfile. If all gems are found, Bundler prints a success message and
exits with a status of 0. If not, the first missing gem is listed and
Bundler exits status 1.

The Gemfile generally doesnot match with the Gemfile.lock becoz the bunder would resolve all the dependencies of the Gem and would place them under name of the Gem in the tree fashion. Moreover, the purpose of Gemfile.lock is simply to resolve the version numbers and other dependencies in case of any conflict which may arise when Bunder finds a number of compatible gems during bundle install.
When you perform the bundle update command, the Gemfile.lock is removed and a new Gemfile.lock is generated with new dependencies...

Related

How to run Bundle after installing?

I have done
gem install bundle
inside my directory that I have a git repository. But now when I try to run it with
bundle
run bundle
bundle install
it says:
Could not locate Gemfile.
How would I check that it has installed ?
It looks like it installed the gem correctly, however, you need to create a file named Gemfile for bundler to know what gems it should install. This file should be in your project's root. You can create one manually, or run bundle init to have a default one generated.
You can read more about the Gemfile in the docs

How to install additional gems with bundler in production environment?

I have a staging server. And I've got some issue I'd like to investigate right there. But I forgot to add byebug to Gemfile. I can surely add it locally, run bundle, commit to repository, deploy. But isn't there an easier way?
When I try to change Gemfile remotely and run bundle I get:
You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.
If this is a development machine, remove the /home/gccs/website-backend/releases/20161018143057/Gemfile freeze
by running `bundle install --no-deployment`.
You have added to the Gemfile:
* byebug
Gems are installed with capistrano, basically, like so:
bundle install --path /home/user/app/shared/bundle --without development test --deployment --quiet
Edit .bundle/config changing BUNDLE_FROZEN: '1' to '0' (or removing it) is enough in order to be allowed by Bundler to manage gems in a deployment environment. Then you can edit the Gemfile, run bundle, restart your application and the custom gems are ready to be used.
If you intend to use them outside of the application runtime (f.e. if you need pry in rails console) restarting the server is not needed.
The reason why you're unable to install additional gems is because the bundle is frozen. You can check it like so:
$ grep FROZEN .bundle/config
BUNDLE_FROZEN: '1'
If you remove the line (as suggested by mdesantis) or change "1" to "0", you'll be able to install whatever gems you like, as if it were developer machine. But generally it's best to restore the value, if no more needed. Not sure if bundler will do that automatically on next deploy.

Bundler: using shared gem when it exists, rather than downloading from gem server

Say, I have Gemfile like following.
source "GEM_REPOSITORY"
gem 'gem_A'
# gem_A has no additional dependency
gem 'gem_B'
# gem_B depends on gem_B_1 and gem_B_2
When I run bundle install, I want Bundler to do the following.
If a gem already exists in "local system-wide gems", it copies the gem from local.
If a gem doesn't exist in local, it looks for GEM_REPOSITORY.
I looked for some related articles, and found some of likely-answers like
Ruby Bundler multiple sources in Gemfile
SOURCE PRIORITY
But none of the above looks like the answer for me.
Using source repository priority does't work. Because in the example above, if dependent gem (say, gem_B_1) exits in local but the target gem (gem_B) doesn't exist in local, it'll download both of above from the remote repository.
Are there any work around for doing this?
If not, don't you guys think it's necessary considering the cost of the implementation and the effect?
This is the current behavior.
When running gem install, directly or via bundle install, gem will first build a dependency graph with all the needed gems. If the gem is found locally it will use it, otherwise it will try to download it from the specified source.
If you want, try it yourself.
bundle gem gem_a
bundle gem gem_b
cd gem_a
vim gem_a.gemspec
add
spec.add_dependency 'multi_json', '~> 1.10.1'
or any dependency you want to the gem and run bundle install.
cd ../gem_b
vim Gemfile
and add
gem 'gem_a', path: '../gem_a'
then run
bundle install --verbose
you will see that the multi_json or whatever dependency of gem_a uses the local version and does not download anything.
This is of course also true for gems from remote sources.

How to see the dependency tree just from Gemfile?

I am getting the following error when doing bundle install
Make sure that `gem install couchbase -v '1.3.3'` succeeds before bundling.
Now, i have not included this gem in the Gemfile, so it's coming from some dependency. How can i figure out which gem is dependent on this couchbase gem?
Since bundle install is failing and I don't have Gemfile.lock to figure out this dependency.
gem dependency (with no args) should show you all gems from current system with their dependencies.
bundle exec gem dependency will show you for the current Gemfile
Edit:
You can also do gem dependency -R (or just dep instead of dependency) if you want to find out which gems use specific (or all) gems.
For deeper dependencies I'd parse output (regex maybe?) of first gem dependencies, pick gem's names and call gem dep on each of them, but that's just a loose idea.
You can also use bundler to create a dependency graph.
Install graphviz:
gem install ruby-graphviz
and then:
bundle viz
Here are an example of a newly created Rails app:
You can also play with the options:
bundle help viz

Bundling local gem (that I'm developing) does not seem to include lib directory (using rvm)

I'm trying to develop a gem locally, and have installed it with Bundler.
My Gemfile looks like this:
source "http://rubygems.org"
gemspec
And my gemspec is a standard gemspec file.
I can install the gem with 'bundle install' in the directory, and i see the local gem and all it's dependencies install:
bundle install
Using rack (1.3.4)
Using tilt (1.3.3)
Using sinatra (1.3.1)
Using {my gem} (0.0.2) from source at .
Using bundler (1.0.21)
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
However, when I do a 'gem list', my gem is not included in the list of gems - which is my guess as to why my bin directory does not appear in the path. Is there a way to test a local gem and include it in the list of installed gems using bundler, so that the bin directory properly works?
Easiest way to get rid of bundler: command not found: {your bin executable}:
git add bin/* # git-ls-files will now list your bin executables.
bundle install
# No git-commit necessary.
bundle exec <MY_BIN_EXECUTABLE>
gem list shows your system installed gems, not the gems in your Bundle (this are often the same but not always--as in this case). When you're using Bundler, you should always execute gem executables with bundle exec so that Bundler can set up the environment for you. So, if you have a binary called, for example, mygem, you should use bundle exec mygem.
See more info at Bundler's site or in the manpage.
[Edit]
Also be sure that your gemspec includes a bin directory! Common convention is to create a directory called bin at the same level as your lib directory, put your binaries in there, and then add this as the directory in your gemspec. If you don't do this, Bundler won't expose your binaries!
I had this problem too.
Make sure the executables and default_executable lines don't contain 'bin/'. Then:
git add add . # You can be more precice if you want.
git commit -m "My lousy commit message."
bundle install
bundle exec <binaryname>

Resources