Skip git source exclusion when lockfile cannot backfill#9544
Merged
Conversation
hsbt
reviewed
May 14, 2026
| expect(the_bundle).not_to include_gems("development_gem 1.0") | ||
| end | ||
|
|
||
| it "resolves indirect dependencies from a git source not in the requested groups", ruby: ">= 3.3" do |
Member
There was a problem hiding this comment.
I think this Ruby 3.3 guard is unnecessary for this and next examples. Can you try to remove them?
Contributor
Author
There was a problem hiding this comment.
Thanks for the review. Removed ruby: ">= 3.3" guard from both specs.
The git source exclusion in `find_source_requirements` introduced by ruby#9234 relies on `locked_requirements` to backfill the gap for sources used only by --without groups. Without a Gemfile.lock — e.g. an initial `BUNDLE_ONLY=ci bundle install` where a default-group gem from a git source is shifted into the "excluded" set — that fallback is absent, and the source's indirect dependencies fall through to the default rubygems source, causing resolution to fail. Gate the exclusion on `nothing_changed?` so it only applies when the lockfile is guaranteed to cover the excluded sources. Fix ruby#9536 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hsbt
approved these changes
May 14, 2026
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was the end-user or developer problem that led to this PR?
#9536: starting with Bundler 4.0.7,
BUNDLE_ONLY=<group> bundle installfails with "Could not find compatible versions" when the Gemfile has a default-group gem fetched from a git source and no Gemfile.lock is present. Reproducer from the issue:Bundler 4.0.6 succeeds; 4.0.7 — 4.0.11 fail. The regression is between those tags.
What is your fix for the problem, implemented in this PR?
Diagnosis
The regression was introduced by #9234, which added
needed_git_sources/excluded_git_sourcesand threadedexcluded_git_sourcesintoBundler::Definition#find_source_requirements:With
BUNDLE_ONLY=ci:requested_groups = [:ci]dependencies_for([:ci])only containsrubocop(a rubygems source)needed_git_sourcesreturns[], so the rails-git source (used by the default-groupactiverecord) is treated as excludedsource_map.all_requirementsthen skips that source when filling indirect-dependency mappingsactivesupport(a sibling spec in the rails git tree) is not mapped to rails-git, so the resolver looks for it in the default rubygems source, doesn't find= 8.2.0.alpha, and gives upThe #9234 spec only passed because it pre-created a complete lockfile; with
nothing_changed?true,source_map.locked_requirements(merged a few lines down) backfilled the gap. Without a Gemfile.lock that fallback is absent.Fix
Gate the exclusion on
nothing_changed?so it only applies when the lockfile is guaranteed to cover the excluded sources:nothing_changed?is true → behavior identical to fix(bundler): only preload git sources for requested groups #9234 (andnothing_changed?itself implieslockfile_exists?and that@missing_lockfile_dep/@locked_spec_with_missing_deps/@locked_spec_with_invalid_depsare all false, solocked_requirementsreally does cover the excluded source).nothing_changed?is false → fall back to passing[], i.e. the resolver sees every git source (the pre-fix(bundler): only preload git sources for requested groups #9234 behavior for this case).The
needed_git_sourcesfilter inpreload_git_sourcesis left in place, so #9234's parallel-preload optimization for--without-only git sources is preserved.Alternatives considered
bundle install --without devis run with a complete lockfile and a private dev git URL). Rejected.dependencies_for(requested_groups)so excluded git sources are not even on the dependency graph. This would fix BUNDLE_ONLY=<name> bundle install raises "Could not find compatible versions" #9536 too and would also let--withoutskip private git sources without a lockfile, but it changes Bundler's "complete lockfile" invariant. Too large for this regression fix; left for a separate design discussion.End-to-end verification
Verified on Fedora with the exact reproducer from #9536, using
GemfilewithoutGemfile.lock:BUNDLE_ONLY=ci bundle installMake sure the following tasks are checked
Two regression specs cover both branches of
find_source_requirements:source_map.all_requirements(excluded)(compact_index dependency API, the default path)Source::RubygemsAggregate.new(sources, source_map, excluded)(via theendpoint_api_forbiddenartifice)The existing #9234 spec (
"works if you exclude a group with a git gem") is unchanged and still passes.