Skip to content

Fix transformRuleInput prefix collision between fine-grained hub and spoke repos - #467

Open
hazel-sudzilouski-ai wants to merge 2 commits into
Tinder:masterfrom
hazel-sudzilouski-ai:hazel-sudz/fix-finegrained-prefix-collision
Open

Fix transformRuleInput prefix collision between fine-grained hub and spoke repos#467
hazel-sudzilouski-ai wants to merge 2 commits into
Tinder:masterfrom
hazel-sudzilouski-ai:hazel-sudz/fix-finegrained-prefix-collision

Conversation

@hazel-sudzilouski-ai

Copy link
Copy Markdown

Summary

--fineGrainedHashExternalRepos matching in BazelRule.transformRuleInput used an unbounded string prefix (ruleInput.startsWith(it)). With hub-and-spoke external repos — e.g. rules_python's pip_parse in WORKSPACE mode, with a @pip hub of alias packages and one @pip_<pkg> spoke repo per package — every spoke label (@pip_numpy//...) prefix-matches the fine-grained hub name (@pip), so it is never rewritten to its //external:pip_numpy synthetic target. That seed is the only node whose hash flips when the spoke's pinned version changes (the version literal lives in the spoke repository rule's attrs), so consumers behind hub aliases were silently dropped from the impacted set on version bumps.

Related shape: the alias-wrap chain discussed in #197.

Fix: match repo names up to the // boundary (ruleInput == it || ruleInput.startsWith("$it//")).

  • First commit — the fix + a BazelRuleTest unit test pinning the rewrite behavior.
  • Second commit — a WORKSPACE-mode e2e fixture (hub_spoke_external: custom repository rule modeling the pip hub/spoke shape) + E2ETest.testHubSpokeVersionBumpImpactsConsumer_fineGrainedHubPrefixCollision, modeled on the issue-197 regression test.

Test plan

  • Red/green on the new e2e test: with the fix reverted to master it fails exactly on the consumer assertion (Got impacted: [//external:pip_numpy] — the orphaned spoke seed) while the seed-flip sanity assertion holds; with the fix it passes in ~9s.
  • bazel test //cli:BazelRuleTest //cli:RuleHasherTest — pass.
  • Full bazel test //cli:E2ETest — 39/39 pass (281s).
  • bazel run //cli/format — clean.
  • Validated at scale against a large internal monorepo replay of a real pip version bump: previously 0 of the directly-dependent tests were selected with the hub listed fine-grained; with this fix the full transitive consumer closure is selected, at no additional hashing cost (the spoke repos stay coarse — no wheel materialization).

🤖 Generated with Claude Code

hazel-sudzilouski-ai and others added 2 commits August 18, 2026 15:32
…spoke repos

fineGrainedHashExternalRepos matching used an unbounded string prefix, so
with hub-and-spoke repos (rules_python pip: @pip hub, @pip_<pkg> spokes) a
spoke label looked like it belonged to the fine-grained hub and was never
rewritten to its //external:<spoke> synthetic target -- the only node whose
hash flips when the spoke's pinned version changes. Consumers behind hub
aliases were therefore never impacted by version bumps.

Match on the full repo name up to the // boundary instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
New WORKSPACE-mode fixture (hub_spoke_external) models pip-style
hub-and-spoke external repos with a custom repository rule: a @pip hub of
alias packages in front of a @pip_numpy spoke whose repository-rule attrs
embed the pinned version. Bumping the version flips only the
//external:pip_numpy seed; the consumer behind the hub alias must follow
the chain @pip//numpy:pkg -> @pip_numpy//:lib -> //external:pip_numpy.

Fails without the transformRuleInput boundary fix (the spoke label
prefix-matched the fine-grained hub name and was never rewritten to its
seed); passes with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@hazel-sudzilouski-ai

Copy link
Copy Markdown
Author

@tinder-maxwellelliott we noticed this issue while using bazel-diff for rules_python in an internal repo.

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.

1 participant