Skip to content

Add support for Artifactory and Github Packages gem sources#1

Open
soulcutter wants to merge 8 commits into
masterfrom
artifactory-support
Open

Add support for Artifactory and Github Packages gem sources#1
soulcutter wants to merge 8 commits into
masterfrom
artifactory-support

Conversation

@soulcutter
Copy link
Copy Markdown

@soulcutter soulcutter commented May 29, 2026

Problem

This tool assumes that https://rubygems.org is always the gem source. As a result gems that are hosted on a different registry that are not in rubygems.org - such as private gems - will not be counted by the tool.

What this does

Based on @bryan-ash 's work in jaredbeck#55 to support Github Packages, this refactors the internal api towards being extensible to other gem sources, and then uses that to add support for Artifactory using the private API token configured in bundler.

GemSource Architecture

Most changes are on the lefthand side of this diagram where the data is supplied for the pre-existing reporting calculations.

flowchart LR
    URL[/"source_url<br/>(from Gemfile.lock)"/]
    Factory{{"GemSource.for(source_url)"}}

    subgraph Adapters["GemSource adapters"]
        RG[Rubygems]
        AF[Artifactory]
        GP[GithubPackages]
        UN[Unsupported]
    end

    Gem["Models::Gem"]
    Report["Reports::Base<br/>(Console / JSON)"]

    URL --> Factory
    Factory -- rubygems.org --> RG
    Factory -- "*.jfrog.io" --> AF
    Factory -- rubygems.pkg.github.com --> GP
    Factory -- other --> UN

    Adapters -- "release_date(name, version)<br/>versions_sequence(name)" --> Gem
    Gem -- "name<br/>libyears<br/>version_number_delta<br/>version_sequence_delta" --> Report
Loading

This is a lot of new code

The refactor introduces a lot of new tests for new parts of the API, and the other big part is that the Artifactory implementation itself is a bit complicated. There's no getting around this being a significant architecture change of the internals.

Future

We should contribute this upstream to https://github.com/jaredbeck/libyear-bundler . This is fork intended to be temporary, but cannot predict if it will be accepted or when it might be considered. And maybe this isn't fully baked yet.

bryan-ash and others added 8 commits May 29, 2026 14:54
Parses Gemfile.lock to detect gem sources and queries
appropriate APIs instead of hardcoding rubygems.org for
all gems. Supports GitHub Packages via gh CLI when
available, gracefully skipping private gems otherwise.

Eliminates 404 errors when analyzing projects with gems
from private registries or GitHub Packages.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Separated out the `gh`-based and rubygems-based implementations of
Gemfile sources. This exposed a place where caching always used
RubyGems, so that also got fixed in these changes. Mostly this behaves
the same as before otherwise.
This was common behavior in every GemSource implementation, so exposed
it in the `GemSource::Base` class api.
This also adds documentation in the README and some documentation on the
general-purpose classes that are relevant to implementations of
different gem sources.
When a Gemfile is explicitly passed, it is used to configure Bundler so that
resolving the Gemfile and Gemfile.lock paths is always consistent with Bundler.

When no Gemfile is explicitly passed, it uses Bundler's default behavior.

Before these changes there was an inconsistency where the implicit
Gemfile behavior was different (and wrong) compared to the explicit
Gemfile behavior. This ensures it's both consistent and correct.
versions_sequence in Unsupported, GithubPackages, and Artifactory now
report the problem and return [] instead of raising, so one bad source
can't abort the report.

Also fix two --releases crashes against Artifactory:
- extract_version parsed the first hyphen-separated token from each
  matching artifact, so unrelated gems sharing a prefix (e.g.
  `datadog-ruby_core_source.gem` matching `datadog-*.gem`) produced
  invalid versions that blew up Gem::Version.new. Parsing now picks
  the longest leading substring accepted by Gem::Version.correct?.
- VersionSequenceDelta.calculate returned nil - nil (TypeError) when a
  version wasn't in the sequence; it now returns 0.

Reports::Console#put_line_summary rescues per-metric errors, matching
Reports::Base#to_h, so a single bad gem can't abort the line summary.

Expose GemSource::Base#problem_reporter= for IO injection.
@soulcutter soulcutter force-pushed the artifactory-support branch from b161ed3 to fa8b28b Compare May 29, 2026 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants