fix(bazel): honor --no-keep_going when querying Bzlmod repositories - #508
Merged
tinder-maxwellelliott merged 2 commits intoSep 23, 2026
Merged
Conversation
Previously, `query_all_targets_with()` silently fell back to an empty Bzlmod repository list (`Vec::new()`) whenever `bazel mod graph`, `bazel mod dump_repo_mapping`, `bazel mod show_repo`, or `bazel mod graph --output=json` failed, even when `--no-keep_going` (`!self.keep_going`) was in effect. In Bzlmod workspaces, silently dropping all `//external:*` synthetic repository targets on one revision causes every rule with an external dependency (`@repo//...` -> `//external:repo`) to have a mismatched Rule digest between `startingHashes` and `finalHashes`, resulting in mass false-positive target invalidation across the workspace. With this change: - If `MODULE.bazel` is present (and Bzlmod is not explicitly disabled via `--noenable_bzlmod` / `--enable_bzlmod=false`) and `bazel mod graph` fails while `!self.keep_going`, `check_bzlmod_enabled()` returns an `Err` with the stderr output instead of silently treating the workspace as legacy. - When `!self.keep_going`, errors from `version()`, `query_bzlmod_repos()`, and `module_graph_json()` are propagated instead of swallowed via `.unwrap_or_else(|_| Vec::new())`. - When `--keep_going` (`self.keep_going == true`) is enabled, the existing warning and partial-graph fallback behavior is preserved.
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.
Summary
When
generate-hashes(orserve) runs with--no-keep_going(the default when--keep_goingis not passed),query_all_targets_with()previously swallowed failures inbazel modsubcommands and silently returned an emptyVec::new()of//external:*synthetic Bzlmod repository targets while still exiting0.When
startingHashesandfinalHashesare generated across two revisions and one invocation experiences a transientbazel modfailure (or lockfile/extension evaluation error) while the other succeeds, one hash file contains all//external:<repo>targets and the other contains zero//external:<repo>targets. Becausetransform_external_input()rewrites every external rule input (@repo//pkg:target->//external:repo) andDigestBuilder::digest_rule()only hashes dependencies present in the target map (if let Some(dependency_digest) = self.target(input, visited)?), every workspace rule that depends on any external repository receives a different rule digest betweenstartingHashesandfinalHashes, causing mass false-positive target invalidation across the workspace.This PR updates
src/bazel.rsto honor!self.keep_going(--no-keep_going) during Bzlmod detection and repository hashing, while preserving the existing partial-graph warning and fallback behavior when--keep_going(-k) is enabled.Root cause
In
src/bazel.rs:is_bzlmod_enabled()ranbazel mod graphand collapsed any non-zero exit status or execution error intofalse(unwrap_or(false)). IfMODULE.bazelwas present in the workspace andbazel mod graphfailed transiently,query_all_targets_with()anddependency_fingerprint()silently treated the workspace as a legacy non-Bzlmod workspace (Vec::new()Bzlmod repos /mode:legacyfingerprint).query_all_targets_with()calledself.query_bzlmod_repos(&mut transform).unwrap_or_else(...), logging[Warn] failed to hash Bzlmod repositoriesand returningVec::new()even whenself.keep_goingwasfalse.query_bzlmod_repos()calledself.module_graph_json().unwrap_or_default(), silently dropping inter-module dependency edges (//external:<dep>) on//external:<repo>targets ifbazel mod graph --output=jsonfailed.What changed
check_bzlmod_enabled(&self) -> Result<bool>:MODULE.bazelexists inself.workspace(and Bzlmod is not explicitly disabled via--noenable_bzlmodor--enable_bzlmod=false|0|no).MODULE.bazelis present and!self.keep_going, a failure inbazel mod graphnow returns anErrwith the exit status andstderroutput instead of silently returningfalse.query_all_targets_with(&self, ...)&query_bzlmod_repos(&self, ...):!self.keep_going, errors fromcheck_bzlmod_enabled(),self.version(),self.query_bzlmod_repos(), andself.module_graph_json()are propagated asErrso the CLI exits non-zero (allowing callers/CI to detect the failure or retry).self.keep_goingistrue(--keep_going/-k), the existing[Warn]diagnostic andVec::new()/ empty-edge fallback behavior is preserved.Verification
bazel test //src:rust_tests //src:cli_testsbazel::tests::check_bzlmod_and_query_bzlmod_repos_honor_keep_going)bazel test //:rust_clippy_check //:rust_format_checkbazel test //tools/... --enable_bzlmod=true --enable_workspace=falsemake coveragesrc/bazel.rs: 91.68%, overall main-source line coverage: 94.38% >= 90.00% threshold)