Problem
bazel-diff requires a full Bazel invocation to compute target hashes. In large monorepos, this is the dominant cost — Bazel's startup, analysis phase, and hash generation can take several minutes even for trivial PRs where only a handful of source files changed.
For CI workflows that need to scope test runs quickly, this overhead is the bottleneck.
Observation
In the common case — when only source files (.go, .java, .proto, .kt, etc.) change and no build configuration is touched — the reverse-dependency graph is fully derivable by statically parsing BUILD / BUILD.bazel files. No Bazel invocation is needed to answer: "which targets are transitively affected by these changed files?"
Proposed approach
Classify changed files into two buckets:
| Changed file type |
Action |
| Source files only |
Walk static reverse-dep graph from BUILD files → emit impacted targets |
.bzl, MODULE.bazel, WORKSPACE, go.mod, go.sum |
Fall back to full bazel-diff (macros/generated targets may have changed) |
The static path runs in seconds. The fallback preserves correctness when build configuration changes.
Trade-offs
- Correctness gap: Static parsing cannot handle
select(), Starlark macros, or generated BUILD files. The fallback covers these cases.
- Coverage: In most feature branches, build config files don't change — the static path handles the majority of CI runs.
- Complexity: Adds a secondary code path; the fallback keeps the existing behavior as the safety net.
Request
Would the maintainers consider a --static or --fast mode that applies this strategy, with automatic fallback? Happy to discuss trade-offs or contribute.
Problem
bazel-diffrequires a full Bazel invocation to compute target hashes. In large monorepos, this is the dominant cost — Bazel's startup, analysis phase, and hash generation can take several minutes even for trivial PRs where only a handful of source files changed.For CI workflows that need to scope test runs quickly, this overhead is the bottleneck.
Observation
In the common case — when only source files (
.go,.java,.proto,.kt, etc.) change and no build configuration is touched — the reverse-dependency graph is fully derivable by statically parsingBUILD/BUILD.bazelfiles. No Bazel invocation is needed to answer: "which targets are transitively affected by these changed files?"Proposed approach
Classify changed files into two buckets:
BUILDfiles → emit impacted targets.bzl,MODULE.bazel,WORKSPACE,go.mod,go.sumbazel-diff(macros/generated targets may have changed)The static path runs in seconds. The fallback preserves correctness when build configuration changes.
Trade-offs
select(), Starlark macros, or generatedBUILDfiles. The fallback covers these cases.Request
Would the maintainers consider a
--staticor--fastmode that applies this strategy, with automatic fallback? Happy to discuss trade-offs or contribute.