Skip to content

Include prerelease gems in compact index during incremental update#108

Open
sudoremo wants to merge 3 commits intorubygems:mainfrom
sudoremo:fix-prerelease-compact-index
Open

Include prerelease gems in compact index during incremental update#108
sudoremo wants to merge 3 commits intorubygems:mainfrom
sudoremo:fix-prerelease-compact-index

Conversation

@sudoremo
Copy link
Copy Markdown

@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
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
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
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
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 rubygems#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
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.

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