Skip to content

feat: add RubyGems registry support#60

Open
kylesnowschwartz wants to merge 1 commit into
vercel-labs:mainfrom
kylesnowschwartz:feat/rubygems-registry-rebased
Open

feat: add RubyGems registry support#60
kylesnowschwartz wants to merge 1 commit into
vercel-labs:mainfrom
kylesnowschwartz:feat/rubygems-registry-rebased

Conversation

@kylesnowschwartz

Copy link
Copy Markdown

Summary

Re-submission of #43 (Matt Van Horn's RubyGems registry support), rebased onto current main with the remove.rs fix the review bot flagged on the original PR, plus two follow-on fixes surfaced during review.

Adds gem:, ruby:, and rubygems: prefixes to fetch Ruby gem source code via rubygems.org API. Same shape as npm, PyPI, and crates.io.

Usage

opensrc path gem:rails
opensrc path ruby:sidekiq
opensrc path gem:nokogiri@1.16.0

Also adds --rubygems to opensrc clean and shows RubyGems in opensrc list.

What changed vs #43

  • Rebased onto current main. Document fetch command, fix search index, add type-check CI, structured error handling #56's structured-error refactor (April 30) replaced Box<dyn std::error::Error> with the crate's typed Error/Result across all registries. rubygems.rs now uses Error::PackageNotFound, Error::HttpStatus, and Error::NoRepoUrl to match the other registry modules.
  • Resolved the list.rs conflict introduced by Add opensrc fetch subcommand #53's opensrc fetch subcommand. The empty-state hint uses fetch examples to match the post-Add opensrc fetch subcommand #53 style.
  • Added Registry::RubyGems to the fallback registry scan in remove.rs, the issue the review bot flagged on feat: add RubyGems registry support #43. Without it, RubyGems packages could only be removed by an explicit gem: prefix.
  • Tightened the remove.rs prefix scoping. The cross-registry fallback now only fires when the user did not supply an explicit prefix, so opensrc remove gem:rails no longer risks deleting a cached npm/PyPI/crates rails when no gem rails is present. Added a was_explicit: bool field to DetectedRegistry to carry the prefix information out of detection.
  • Collapsed the rubygems.rs error variant. The single-call V2 endpoint can't distinguish "gem missing" from "version missing", so a misleading VersionNotFound was replaced with a single PackageNotFound reporting the user's spec verbatim.

Known limitations (out of scope here)

Three concerns surfaced during review that exist in current main for every registry, not just RubyGems. Flagging for maintainer visibility; happy to open separate PRs if helpful:

  1. Substring-based host validation. is_git_repo_url in core/registries/mod.rs uses url.contains("github.com"), and authenticated_clone_url rewrites credentials via str::replace. A malicious package whose repository URL contains a known host as a substring (e.g. https://github.com.evil.example/owner/repo) passes validation and would receive GITHUB_TOKEN. Fix: parse with url::Url and require exact host match.

  2. Default-branch fallback silently mislabels cache. clone_at_tag in core/git.rs treats a tagless default-branch clone as success after v{version} and {version} both miss. sources.json then records the package at the requested version while the cache holds default-branch HEAD. RubyGems is more likely to hit this than npm/crates because gem repos don't uniformly tag with the v prefix.

  3. URL encoding inconsistency. npm.rs encodes package names with urlencoding::encode; pypi.rs, crates.rs, and this PR's rubygems.rs interpolate raw. Probably benign for the constrained name characters these registries allow, but worth aligning.

Testing

cargo fmt --manifest-path packages/opensrc/cli/Cargo.toml --check
cargo clippy --manifest-path packages/opensrc/cli/Cargo.toml -- -D warnings
cargo test --manifest-path packages/opensrc/cli/Cargo.toml -- --test-threads=1

All 107 tests pass. fmt and clippy clean.

Credit

Original work by @mvanhorn in #43. The squashed commit keeps Matt as Author. I'm listed as Co-author for the rebase, error-pattern port, remove.rs scoping fix, and error-variant collapse.


This PR was AI-generated and human-reviewed. The rebase, error refactor, and remove.rs fixes were prepared with Claude Code under my review, with adversarial review from Codex and Gemini before submission.

Add gem:, ruby:, and rubygems: prefixes to fetch Ruby gem source code
via rubygems.org API. Same shape as npm, PyPI, and crates.io.

Usage:
  opensrc path gem:rails
  opensrc path ruby:sidekiq
  opensrc path gem:nokogiri@1.16.0

The API returns source_code_uri, which maps to a git clone URL.
Falls back to homepage_uri if source_code_uri is absent.

Also adds --rubygems to clean and shows RubyGems in list output.

Rebased onto current main against vercel-labs#56's structured-error refactor, and
adds the Registry::RubyGems arm in remove.rs that the review bot
flagged on the original PR.

Also tightens remove.rs to skip the cross-registry fallback when the
user supplied an explicit prefix, so `opensrc remove gem:foo` cannot
delete a cached npm/PyPI/crates `foo`. Collapses the rubygems.rs
VersionNotFound variant into PackageNotFound, since a single-call V2
endpoint can't tell "gem missing" from "version missing" apart.

Co-authored-by: Kyle Snow Schwartz <kyle.schwartz@envato.com>
@vercel

vercel Bot commented May 19, 2026

Copy link
Copy Markdown

@mvanhorn is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@mvanhorn

Copy link
Copy Markdown

Thanks for picking this up @kylesnowschwartz -- happy to see #43's work landed under your stewardship with the co-authorship credit preserved. Two of the changes you added are real improvements I missed:

  • The was_explicit: bool field on DetectedRegistry is the right scoping for the remove.rs fallback. Without it, opensrc remove gem:rails could nuke a cached npm rails. Glad you caught that.
  • The PackageNotFound collapse is more honest than the original VersionNotFound/PackageNotFound split given that the V2 endpoint can't distinguish the two.

The three out-of-scope concerns all look legitimate to me on a re-read of core/registries/mod.rs and core/git.rs. The substring host validation in particular (url.contains("github.com")) is worth tightening soon -- happy to take any of those if maintainers want them split.

LGTM as a contributor; deferring to vercel-labs on the merge call.

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