Skip to content

Include prerelease gems in compact index during incremental update#108

Merged
hsbt merged 3 commits into
ruby:mainfrom
sudoremo:fix-prerelease-compact-index
May 7, 2026
Merged

Include prerelease gems in compact index during incremental update#108
hsbt merged 3 commits into
ruby:mainfrom
sudoremo:fix-prerelease-compact-index

Conversation

@sudoremo
Copy link
Copy Markdown
Contributor

@sudoremo sudoremo commented Mar 9, 2026

Summary

Fixes #48.

In update_index, the call to update_compact_index only received released specs, excluding prerelease gems from the compact index files (versions, info/<gemname>). Since build_compact defaults to true and modern Bundler prefers the compact index over legacy specs files, prerelease gems were effectively invisible after an incremental gem generate_index --update — even though they were correctly added to prerelease_specs.4.8.gz.

The fix passes all specs (both released and prerelease) to update_compact_index, consistent with how build_compact_index already handles both during a full generate_index.

Changes

  • lib/rubygems/indexer.rb: Pass specs instead of released to update_compact_index
  • test/rubygems/test_gem_indexer.rb: Add assertions for prerelease gem d-2.2.a in compact index after update_index

@sudoremo
Copy link
Copy Markdown
Contributor Author

The latest addition should fix all unit tests.

@hsbt
Copy link
Copy Markdown
Member

hsbt commented Apr 8, 2026

Please keep the existing assert_equal for info/d and just append assertions for the pre-release entry (2.2.a).

The current change loosens the validation by replacing assert_equal with assert_match/start_with?, which reduces regression coverage.

@sudoremo
Copy link
Copy Markdown
Contributor Author

sudoremo commented Apr 8, 2026

Thanks @hsbt for your feedback. The requested changes have been implemented.

assert_equal <<~VERSIONS_FILE, File.read(File.join(@indexerdir, "versions"))
#{versions_file.chomp}
d 2.1 #{file_md5(File.join(@indexerdir, "info", "d"))}
d 2.1,2.2.a #{file_md5(File.join(@indexerdir, "info", "d"))}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, test is super long and not simple to follow. I'm not 100% sure this is correct, since new version should be on separate line (appended) when modifying existing file to keep it partially cacheable. And compacted later on demand. Not sure this tests appends or does new index from scratch. Are there tests for both case? I can take a look later to understand the tests if needed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! This test exercises the incremental update_index path (not a full rebuild). Both d-2.1 (released) and d-2.2.a (prerelease) are added in the same update_index call, so compact_index_gems groups them into a single CompactIndex::Gem, and VersionsFile#contents appends one line per gem per update — hence d 2.1,2.2.a on a single line.

This is consistent with how a full generate_index works too — see test_build_indices where the versions file has d 2.0,2.0.a,2.0.a-x86-linux,2.0.b on a single line.

The info/d file does correctly have each version on its own line (appended to the existing content via update_compact_index at line 524).

So to summarize the test coverage:

  • Full rebuild: test_build_indices / test_generate_index
  • Incremental update (append): test_update_index — this is the one changed here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what happens on rubygems.org, in there new gems are appended (until compacting happening each month).

https://github.com/rubygems/rubygems.org/blob/edcc71a94163f50e9c95f7467a8d505600ce770d/app/jobs/upload_versions_file_job.rb#L27C34-L27C42

It is to make versions file cacheable at least for one calendar month and you're downloading only increments at that time. If this is testing appending, I assume it should create new line. But it seems this is not new issue with your addition, so maybe ok to accept this for now. I can check in separate PR to add also incremental additions (maybe as an option?).

@sudoremo
Copy link
Copy Markdown
Contributor Author

@hsbt / @simi May I bump this issue again? The bug is currently causing massive slowdowns on our end, as we release multiple pre-releases daily and fully rebuilding the index takes 30-40 minutes. We would therefore really appreciate a timely release of this bugfix. Many thanks for your work.

In `update_index`, the call to `update_compact_index` only received
`released` specs, excluding prerelease gems from the compact index
files (`versions`, `info/<gemname>`). Since modern Bundler prefers the
compact index, prerelease gems were effectively invisible after an
incremental `--update`.

Fix by passing all specs (both released and prerelease) to
`update_compact_index`.

Fixes ruby#48
Replace assert_match/start_with? with assert_equal for the info/d
compact index file, keeping full regression coverage as requested in
review feedback.
@hsbt hsbt force-pushed the fix-prerelease-compact-index branch from f0f0f83 to c30dc55 Compare April 22, 2026 21:03
@hsbt
Copy link
Copy Markdown
Member

hsbt commented Apr 22, 2026

@sudoremo Can you fix test failure at first?

On Ruby < 3.5.0, prerelease gems include a rubygems:> 1.3.1
dependency in their compact index info line. The assertion for the
d-2.2.a prerelease entry added during update_index was missing this
version-conditional suffix, causing failures on Ruby 3.0, 3.1, and
3.2.
@sudoremo
Copy link
Copy Markdown
Contributor Author

@hsbt Good catch — the test failure was caused by a missing version-conditional suffix on the d-2.2.a info line assertion. On Ruby < 3.5.0 (i.e. Ruby 3.0, 3.1, 3.2, JRuby 9.4), prerelease gems include rubygems:> 1.3.1 in their compact index info line, which wasn't accounted for in the new assertion.

Fixed in 6428295 by applying the same #{",rubygems:> 1.3.1" if Gem::VERSION < "3.5.0"} pattern already used at line 143 for the a-3.a entry. Tests should now pass across all CI Ruby versions.

Could you approve the CI run when you get a chance? Since each run requires maintainer approval, iterating on failures is a bit slow on our end.

@sudoremo
Copy link
Copy Markdown
Contributor Author

sudoremo commented May 5, 2026

@hsbt / @simi May I bump this issue again? We would be greatful for a timely release. Thanks for having a look at it.

@simi
Copy link
Copy Markdown
Contributor

simi commented May 5, 2026

@sudoremo the situation is as follows: https://github.com/rubygems/compact_index got archived, probably because it was ported to rubygems/rubygems.org#6404, even it was generic implementation and it was beneficial to keep it independent and discuss potential changes there independent of rubygems.org IMHO. This gem depends (https://github.com/rubygems/rubygems-generate_index/blob/99d4d1f6d22d6e52720e53260b498f9998c76e45/rubygems-generate_index.gemspec#L32) on that one. So I assume this plugin is also soft-deprecated now.

I spoke to RubyGems maintainer and was told, this generator doesn't need to be part of RubyGems (or RubyGems plugin). I do actually agree on that. I have started extraction of it in https://github.com/compact-index/compact_index (for now covering only the original back) and I'm trying to speak to RubyGems.org maintainers to move back to shared solution (and move forward all together). Feel free to open issue in there, I have prototype (not release, pushed yet) for independent gem with CLI to generate compact index in similar way this plugin did.

@hsbt hsbt merged commit dd16fca into ruby:main May 7, 2026
21 checks passed
@hsbt
Copy link
Copy Markdown
Member

hsbt commented May 7, 2026

@sudoremo I released https://github.com/ruby/rubygems-generate_index/releases/tag/v1.2.0 with your fix. Thanks.

@sudoremo
Copy link
Copy Markdown
Contributor Author

sudoremo commented May 7, 2026

Many thanks @hsbt and @simi 🙌

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.

Versions file not updated for RC-releases

3 participants