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:
GIT
which is the first remote source on the list, here telling which commit that we are depending upon specificallyGEM
which list out the the gems that are installed, with versionsPLATFORMS
which is for platform information (for native builds)DEPENDENCIES
which is what comes out of theGemfile
RUBY VERSION
the version of Ruby, including the patch level, that this was bundled withBUNDLED WITH
version 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