Looking at Gemfiles
making sense of Gemfile.lock
- tags
- ruby
- bundler
- packagemanagers
- git
Contents
Bundler is the standard way for Ruby projects to specifiy
dependencies. Let's take a look at how that works, reimplement bundle
outdated, and be able to see the changes that took place between the
build you are using and the latest one.
Ruby ecosystem: Rubygems, Bundler, Gemfile, Gemfile.lock
rubygems is the overall ecosystem, which includes the main
rubygems.org database of shared packages, and how they depend upon
each other. At the heart of it is a gemspec file which describes the
package, files included in it, dependencies, and other metadata.
bundler is the tool that helps you download and install specific gems for
your application. It uses a Gemfile to define what you want, and then
resolves all the dependencies and stores that into a Gemfile.lock file
that contains a list of the exact versions that you are developing
against.
Creating a working Gemfile
First, let's create a project, so we are all working off of the same
thing. We'll add bundler as normal, and then irb from git directly, so
we can see how that changes the Gemfile.lock. So, 3 gems, 2 from
rubygems.org, and one directly from github.
| |
Lets also add in a ruby "2.6.6" line that will tell bundler which
version of Ruby we want to use. This isn't always used, but let's put
it in to flesh out what is generated in the lock file. Feel free to
replace this with whatever version is on your local machine.
This gives us a Gemfile that looks like this:
| |
Doing a bundle add adds the specification to the Gemfile, downloads
the gems and all of their dependencies, resolving specific versions and
downloading those as well. This is specified in the lock file, which
has the main sections:
GITwhich is the first remote source on the list, here telling which commit that we are depending upon specificallyGEMwhich list out the the gems that are installed, with versionsPLATFORMSwhich is for platform information (for native builds)DEPENDENCIESwhich is what comes out of theGemfileRUBY VERSIONthe version of Ruby, including the patch level, that this was bundled withBUNDLED WITHversion information about bundler
| |
Parsing Gemfile and Gemfile.lock together
In normal usage you would have both a Gemfile and a Gemfile.lock.
You'd start up your program using bundle exec which would validate
that the right things were installed, load the gems into the Ruby
environment, and you'd be good to go.
| |
Which yields:
Dependencies irb [">= 0"] bundler ["~> 2.1"] Gem from the local ruby installation bundler 2.1.4 https://github.com/bundler/bundler/ https://bundler.io Gem from rubygems repository https://rubygems.org/ or installed locally gems 1.2.0 https://github.com/rubygems/gems Gem from rubygems repository https://rubygems.org/ or installed locally io-console 0.5.6 https://github.com/ruby/io-console https://github.com/ruby/io-console Gem from rubygems repository https://rubygems.org/ or installed locally reline 0.1.4 https://github.com/ruby/reline Gem from https://github.com/ruby/irb (at master@9bb6562) irb 1.2.4 https://github.com/ruby/irb
So some gems have source_code_uri or source_code_url set, and some
don't have it at all though they point to a github page where
presumably we can figure out where the code is loaded.
For the case of irb the repo is listed in the remote source itself.
The metadata, homepage, etc, are from the gemspec files.
Parsing a Gemfile.lock directly
Let's now look at how to parse a Gemfile.lock of a different project,
where we don't have the original Gemfile handy.
When we load in the lockfile using Bundler::LockfileParser we only
have the gem name, version, and the source from which to get it. We
may or may not have the gemspec on our local machine, and so
additional metadata like the homepage, summary, codeurl, etc haven't
been loaded yet. Let's first print out what we have and then figure
out how to get gem information from the source, name, and version.
| |
Bundler version 2.1.4 Dependencies bundler ["~> 2.1"] gems ["~> 1.2"] irb [">= 0"] Gems gems 1.2.0 Bundler::Source::Rubygems rubygems repository https://rubygems.org/ or installed locally io-console 0.5.6 Bundler::Source::Rubygems rubygems repository https://rubygems.org/ or installed locally irb 1.2.4 Bundler::Source::Git https://github.com/ruby/irb (at master@9bb6562) reline 0.1.4 Bundler::Source::Rubygems rubygems repository https://rubygems.org/ or installed locally
Another thing that's interesting to note is that the version of
bundler itself doesn't show up in the specified gems, though it is
available from the bundler_version method.
Finding outdated gem versions
If you are working with a matching set of Gemfile and Gemfile.lock
files, which most people are, there's a nifty command bundle outdated.
This looks though the gems that you have to see if there's a later
version released.
Let's recreate this using our Gemfile.lock only method so we can look
at lock files and see which gems have updated code.
First we will pull the specs out of the lockfile. Then we will loop
over them, pulling in the infomation from rubygems or wherever the
remote was specified. We aren't doing anything special with git
sourced gems.
| |
Name Current Latest Old Info
gems 1.1.1 1.2.0 Y Ruby wrapper for the RubyGems.org API
io-console 0.5.6 0.5.6 add console capabilities to IO instances.
irb 1.2.4 1.2.4 Interactive Ruby command-line tool for REPL (Read E
json 2.3.1 2.3.1 This is a JSON implementation as a Ruby extension i
reline 0.1.4 0.1.4 Alternative GNU Readline or Editline implementation
This is a very simple project, but we can see that the one gem that we
held back to 1.1.1 instead of the (current) latest of 1.2.0 is
outdated.
Future thoughts
Looking at the Gemfile.lock file we're able to see which versions of
the gems are installed, and we can pull down the git repos of most of
them using the metadata. (Or homepage, for a lot of them.) The
standard bundling tools will create a git tag for each of the
releases, so in our next installment we will start looking at the
code differences between versions, both the commit messages as well
as overall activity in these projects. This should help us understand
how risky the upgrades are, and if we believe in semver.
Previously
Next