Reproducer test for #335 loose substring match in queryTargetsDependingOnModules#346
Closed
tinder-maxwellelliott wants to merge 4 commits into
Closed
Reproducer test for #335 loose substring match in queryTargetsDependingOnModules#346tinder-maxwellelliott wants to merge 4 commits into
tinder-maxwellelliott wants to merge 4 commits into
Conversation
…endingOnModules Issue #335 lists multiple potential fixes; my first PR (#340) covered fix #1 (parser robustness). This PR adds a reproducer for fix #3: the loose substring match in CalculateImpactedTargetsInteractor.queryTargetsDependingOnModules. The current code is: val moduleRepos = allTargets.keys .filter { it.startsWith("@@") && it.contains(moduleName) } .map { it.substring(2).substringBefore("//") } .toSet() `it.contains(moduleName)` is a very loose match. A single changed module like `aspect_bazel_lib` matches every canonical repo whose name starts with that string -- e.g. `@@aspect_bazel_lib+`, `@@aspect_bazel_lib++toolchains+bats_toolchains`, etc. Each match becomes its own serial `bazel query rdeps(//..., @@<repo>//...)` subprocess. On the workspace in #335 that fan-out produced ~5,000 subprocesses and took multiple hours. New test class CalculateImpactedTargetsInteractorIssue335Test: - Wires its own koin module with a mock BazelQueryService that captures every query expression. - Simulates a workspace with one module (aspect_bazel_lib) plus two module-extension repos whose canonical names begin with the same apparent name. - Asserts that resolving the changed module yields exactly ONE rdeps query, scoped to the actual changed repo. @ignore'd until the match is tightened (match canonical repo key exactly, or look up via `bazel mod dump_repo_mapping`). cli/BUILD wires up the new kt_jvm_test target. Refs #335 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
647fa53 to
5fd35f4
Compare
4 tasks
tinder-maxwellelliott
added a commit
that referenced
this pull request
May 18, 2026
…gOnModules (#354) * Add reproducer test for #335 loose substring match in queryTargetsDependingOnModules Issue #335 lists multiple potential fixes; my first PR (#340) covered fix #1 (parser robustness). This PR adds a reproducer for fix #3: the loose substring match in CalculateImpactedTargetsInteractor.queryTargetsDependingOnModules. The current code is: val moduleRepos = allTargets.keys .filter { it.startsWith("@@") && it.contains(moduleName) } .map { it.substring(2).substringBefore("//") } .toSet() `it.contains(moduleName)` is a very loose match. A single changed module like `aspect_bazel_lib` matches every canonical repo whose name starts with that string -- e.g. `@@aspect_bazel_lib+`, `@@aspect_bazel_lib++toolchains+bats_toolchains`, etc. Each match becomes its own serial `bazel query rdeps(//..., @@<repo>//...)` subprocess. On the workspace in #335 that fan-out produced ~5,000 subprocesses and took multiple hours. New test class CalculateImpactedTargetsInteractorIssue335Test: - Wires its own koin module with a mock BazelQueryService that captures every query expression. - Simulates a workspace with one module (aspect_bazel_lib) plus two module-extension repos whose canonical names begin with the same apparent name. - Asserts that resolving the changed module yields exactly ONE rdeps query, scoped to the actual changed repo. @ignore'd until the match is tightened (match canonical repo key exactly, or look up via `bazel mod dump_repo_mapping`). cli/BUILD wires up the new kt_jvm_test target. Refs #335 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fix #335 fix #3: tighten canonical-repo match in queryTargetsDependingOnModules `queryTargetsDependingOnModules` resolved each changed module key to its canonical bzlmod repos by scanning `allTargets.keys` with `it.startsWith("@@") && it.contains(moduleName)`. The `contains` match is far too loose: a single changed module like `aspect_bazel_lib` matched every canonical repo whose name began with that string -- e.g. `@@aspect_bazel_lib+`, `@@aspect_bazel_lib++toolchains+bats_toolchains`, `@@aspect_bazel_lib++toolchains+yq_toolchains`, etc. Each match was then unioned into the rdeps query expression (after the per-repo loop became a single unioned query in an earlier change), but the same fan-out behaviour on older revisions produced ~5,000 serial subprocesses on the workspace in #335 and took multiple hours. Tighten the match to the module's *base* canonical repo only: `<moduleName><sep><versionSegment>` where `<sep>` is `+` or `~` and the remainder contains no further separators. Module-extension repos always layer additional `+`/`~` segments on top and are rejected here. That narrowing is safe because extension-repo content changes already propagate to main-repo consumers through the per-target hash dep chain: `computeSimpleImpactedTargets` runs unconditionally for `@@*` labels and the build-graph hasher folds dep hashes into each rule's hash, so a consumer of a changed extension repo flips its own hash and is picked up without needing an rdeps query targeting the extension repo. The rdeps query exists to catch the harder case -- MODULE.bazel-only bumps that don't flip any hash but do change which version of a base module repo is selected -- and that is exactly the case the base-repo match handles. The reproducer test class from PR #346 had a latent Mockito misuse in its `@Before`: the second `whenever(queryService.query(any<String>()))` stub omits the default-argument matcher and was throwing `InvalidUseOfMatchersException` before any assertion ran. The test was `@Ignore`d so the bug was never observed. Dropping the redundant stub and dropping `@Ignore` -- the first stub already covers the production caller, which always passes `useCquery = false` explicitly. Verification: - `bazel test //cli:CalculateImpactedTargetsInteractorTest` -- PASSED (21 pre-existing tests still pass, including `testUnionsRdepsAcrossChangedModules` which exercises the `~` form through the same code path). - `bazel test //cli:CalculateImpactedTargetsInteractorIssue335Test` -- PASSED (the un-`@Ignore`d reproducer now passes; reverting just the production change reproduces the bug with the loose match yielding `rdeps(//..., @@aspect_bazel_lib+//... + @@aspect_bazel_lib++toolchains+bats_toolchains//... + @@aspect_bazel_lib++toolchains+yq_toolchains//...)`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
@Ignored unit reproducer for #335 fix Update bazel-diff-example.sh #3 (loose substring match inCalculateImpactedTargetsInteractor.queryTargetsDependingOnModules). This is a follow-up to #340, which covered the parser-robustness piece (fix Typos #1) of the same issue.it.contains(moduleName)is a very loose match. A single changed module likeaspect_bazel_libmatches every canonical repo whose name starts with that string —@@aspect_bazel_lib+,@@aspect_bazel_lib++toolchains+bats_toolchains, etc. Each match becomes its own serialbazel query rdeps(//..., @@<repo>//...)subprocess. On the workspace in #335 that fan-out produced ~5,000 subprocesses and took multiple hours.CalculateImpactedTargetsInteractorIssue335Test:BazelQueryServicethat captures every query expression.aspect_bazel_lib) plus two module-extension repos whose canonical names begin with the same apparent name.rdepsquery, scoped to the actual changed repo.The asked-for fix in #335 is either to match the canonical repo key exactly (e.g.
aspect_bazel_lib+— the part before any further+/~), or to look up the repo viabazel mod dump_repo_mappinginstead of a substring scan. Drop@Ignoreonce that lands.This is a test-only change.
cli/BUILDadds the newkt_jvm_testtarget.Test plan
bazel build //cli:CalculateImpactedTargetsInteractorIssue335Testsucceeds.bazel test //cli:CalculateImpactedTargetsInteractorIssue335Test→ PASSED in 0.5s (the new test is@Ignored and skipped).@Ignoreand re-run — exactly onerdepsquery should be captured.🤖 Generated with Claude Code