November 2, 2017·4 min read·engineeringrubypackagesdependencies

RubyGems 2.7 delegates dependency-file setup to Bundler

RubyGems 2.7 uses Bundler for Gem.use_gemdeps and includes Bundler 1.16.0. Its source shows how the dependency-file entry point connects to bundle setup and how the new signout command handles local credentials.

Two dependency tools can expose overlapping entry points while disagreeing about which implementation handles the work. RubyGems 2.7 reduces that overlap for Gem.use_gemdeps by delegating to Bundler. A RubyGems dependency-file request now reaches bundle setup instead of maintaining the previous request-set path as its active implementation.

The release announcement lists vendored Bundler 1.16.0 and Bundler-backed dependency setup among the major changes. Its tagged history dates 2.7.0 to November 2, which is the date used here. The announcement's URL and displayed date use November 1, so the source records differ by a day within the same month.

I find Ruby approachable for larger applications, but overlapping dependency activation paths can make startup harder to explain. Using Bundler behind the RubyGems entry point gives the operation a more concrete implementation to inspect. The useful question becomes which dependency file is selected and how that file reaches Bundler.

The file is selected before setup begins

The tagged RubyGems implementation accepts an optional path to Gem.use_gemdeps. When absent, it looks for RUBYGEMS_GEMDEPS in the environment and returns without setup if no path is provided. The special value - requests searching parent directories for a supported dependency file.

An explicit missing path raises an argument error. A missing file reached without an explicit argument can return without raising through that check. The source records whether the caller supplied the path, so these cases are intentionally distinguishable.

Once a file exists, the active branch sets BUNDLE_GEMFILE to its expanded path if that variable is not already set. It requires Bundler, calls Bundler.setup and returns the requested specifications converted to specifications and sorted by name. The source sets USE_BUNDLER_FOR_GEMDEPS to true, selecting that branch.

The conditional assignment to BUNDLE_GEMFILE is worth reading precisely. It preserves an existing value instead of unconditionally replacing it. An environment that already names a bundle file therefore contributes to which configuration Bundler sees. Following the dependency-file argument alone can miss that existing environment input.

The old Gem::RequestSet path remains in the source under the alternative branch. Its presence does not mean the default operation continues to use it. The constant selecting the Bundler branch is the evidence for the release's changed behavior.

Activation respects an existing process state

The release also allows Gem.finish_resolve to respect already activated specifications. That concerns a process where some gem activation has occurred before another resolution step. Dependency tooling needs to account for the implementation already loaded, not merely choose a version as though the process were empty.

Other listed performance work avoids reloading all local gems repeatedly during dependency resolution and avoids iterating through all loaded specifications in a stub's to_spec operation. These changes reduce metadata work without establishing a new application-level performance figure. The announcement gives the affected operations and repairs, rather than a benchmark for an arbitrary Gemfile.

The release's installation and loading changes belong to the same practical area but have different effects. Resolving a graph, activating a selected gem and converting a stub specification are separate operations. A repair in one should not be advertised as making every stage of package startup faster or equivalent.

I value this distinction because package-manager overhead often appears as one delay before the application starts. The source and release notes identify the actual operations. That makes a reported improvement more useful than a claim that the whole dependency system has become uniformly faster.

Signout changes local credential state

RubyGems 2.7 adds sign-in and signout facilities to the command-line interface. The signout implementation checks the configured credential file, reports when it is absent or read-only, and otherwise calls unset_api_key! on the configuration.

That implementation describes a local credential operation. The command's user-facing message refers to signing out of sessions, but the shown code does not establish server-side revocation of every copy of an API key. Removing the local credential and invalidating a remote credential are different effects, so the latter should not be inferred from the message alone.

The file checks also explain a failed signout without requiring a network diagnosis. An absent credential file means there is no local signed-in state at that configured path. A read-only file prevents the command from changing that state, and the command reports that condition directly.

The new release also improves error messages for runtime requirements and failed installation conditions. Together with the Bundler delegation, these changes clarify how package commands interact with a selected dependency file, existing activation state and local credentials. The tagged source gives each operation a defined behavior, including the environment precedence and credential-file checks that a broad release summary can leave implicit.