Skip to content

feat(gem,maven): extend multi-platform release patching to RubyGems + Maven#91

Merged
Mikola Lysenko (mikolalysenko) merged 1 commit into
mainfrom
feat/multi-platform-gem-maven
May 28, 2026
Merged

feat(gem,maven): extend multi-platform release patching to RubyGems + Maven#91
Mikola Lysenko (mikolalysenko) merged 1 commit into
mainfrom
feat/multi-platform-gem-maven

Conversation

@mikolalysenko
Copy link
Copy Markdown
Collaborator

Summary

Generalizes the PyPI multi-release machinery from #90 (release-variant qualifiers, narrow/broad download, base-PURL remove/rollback) to the other ecosystems that ship multiple platform/release artifacts per package@version:

Ecosystem Variant qualifier Notes
RubyGems ?platform=x86_64-linux one platform gem installed per env — mirrors PyPI exactly
Maven ?classifier=linux-x86_64&ext=jar classifier jars coexist in one version dir (experimental)

NuGet / npm / Cargo / Go / Composer / Deno are unaffected — they ship one artifact per version (platform splits live under separate package names), so they keep the 1:1 PURL-match path.

Shared generalization

  • Ecosystem::supports_release_variants() (Pypi | Gem | Maven) replaces the scattered == Ecosystem::Pypi gates in apply / get / dispatch.
  • Dispatch: dedup_pypi_purls/merge_pypi_qualified → generic dedup_qualified_purls/merge_qualified, now applied to the gem and maven scan blocks. The crawler is queried with base PURLs and the installed variant is resolved by hashing on-disk files — the same model PyPI uses.
  • Plural selector: select_installed_variantselect_installed_variants returning all present-and-matching variants. PyPI/RubyGems install exactly one distribution per env (≤1 match — unchanged), but Maven classifier jars coexist, so several may match. apply.rs applies every matching variant (no early break); the get narrow-filter and rollback dedupe keep all matches.

RubyGems

  • RubyCrawler::parse_dir_name_version now splits at the first dash-digit and drops the trailing -<platform> suffix, fixing a misparse that folded the platform into the version (nokogiri-1.16.5-x86_64-linux → version 1.16.5-x86_64-linux).
  • New locate_gem_dir resolves a base name/version to the installed platform-suffixed gem directory.

Maven

  • No crawler change: find_by_purls already emits the base PURL keyed to the version dir; each classifier variant is hash-resolved against its jar file. Stays behind SOCKET_EXPERIMENTAL_MAVEN; still leaves .jar.sha1 sidecars stale (no fixup — unchanged, out of scope).

Tests

  • in_process_gem_multi_platform.rs — synthetic platform gem (no gem binary) + wiremock: narrow keeps the installed platform, broad keeps all, remove base PURL clears all variants and rolls back, rollback-all exits 0.
  • in_process_remote_ecosystems_apply.rsmaven_multi_classifier test proving the plural selector patches every coexisting classifier jar.
  • Unit tests for gem dir-name platform parsing (incl. the regression case and a trailing-OS-version platform) and the supports_release_variants predicate.

Full workspace suite: 1580 passed, 0 failed; clippy gate clean.

Companion backend change (separate, depscan repo)

The patch API must emit qualified PURLs for gem/maven. In depscan, orgs/patches/{by-package,batch}.ts drop the && type===PYPI gate (normalizeArtifactPURL already converts a non-PyPI artifact_id into qualifiers). Per-platform gem artifact rows already exist; note the autopatch pipeline currently authors gem patches against the canonical platform=ruby artifact, so full per-platform patch authoring is a separate pipeline change.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

… Maven

Generalizes the PyPI multi-release machinery (release-variant qualifiers,
narrow/broad download, base-PURL remove/rollback) to the other ecosystems
that ship multiple platform/release artifacts per package@version:

  * RubyGems — platform gems (`?platform=x86_64-linux`, `?platform=arm64-darwin`)
  * Maven    — classifier jars (`?classifier=linux-x86_64&ext=jar`)

NuGet/npm/Cargo/Go/Composer/Deno are unaffected: they ship one artifact per
version (platform splits live under separate package names), so they keep the
1:1 PURL match path.

Shared generalization:
- Ecosystem::supports_release_variants() (Pypi | Gem | Maven) replaces the
  scattered `== Ecosystem::Pypi` gates in apply/get/dispatch.
- ecosystem_dispatch: rename pypi-specific dedup_pypi_purls/merge_pypi_qualified
  to dedup_qualified_purls/merge_qualified and apply them to the gem and maven
  scan blocks. The crawler is queried with base PURLs and the installed variant
  is resolved by hashing on-disk files — the same model PyPI uses.
- select_installed_variant -> plural select_installed_variants returning ALL
  present-and-matching variants. PyPI/RubyGems install exactly one distribution
  per environment (≤1 match, unchanged), but Maven classifier jars coexist in
  one version dir, so several may match. apply.rs applies every matching variant
  (no early `break`); the get narrow-filter and rollback dedupe keep all matches.

RubyGems:
- RubyCrawler::parse_dir_name_version now splits at the first dash-digit and
  drops the trailing `-<platform>` suffix, fixing a misparse that folded the
  platform into the version (`nokogiri-1.16.5-x86_64-linux` -> version
  `1.16.5-x86_64-linux`). New locate_gem_dir resolves a base name/version to the
  installed platform-suffixed gem directory.

Maven needs no crawler change: find_by_purls already emits the base PURL keyed
to the version directory, and each classifier variant is hash-resolved against
its jar file. Maven stays behind SOCKET_EXPERIMENTAL_MAVEN and still leaves
`.jar.sha1` sidecars stale (no fixup — unchanged).

Tests:
- in_process_gem_multi_platform.rs: synthetic platform gem (no `gem` binary) +
  wiremock — narrow keeps the installed platform, broad keeps all, remove base
  PURL clears all variants and rolls back, rollback-all exits 0.
- in_process_remote_ecosystems_apply.rs: maven_multi_classifier test proving the
  plural selector patches every coexisting classifier jar.
- Unit tests for gem dir-name platform parsing (incl. the regression case and a
  trailing-OS-version platform) and the supports_release_variants predicate.

Full workspace suite: 1580 passed, 0 failed; clippy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mikolalysenko Mikola Lysenko (mikolalysenko) merged commit d1108cb into main May 28, 2026
42 checks passed
@mikolalysenko Mikola Lysenko (mikolalysenko) deleted the feat/multi-platform-gem-maven branch May 28, 2026 21:11
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