skyframe: detect local repositories during package lookup#29218
skyframe: detect local repositories during package lookup#29218abishekgiri wants to merge 5 commits intobazelbuild:masterfrom
Conversation
|
Reopened this change from the neutral branch name local-repo-lookup-fix. The targeted test command is in the PR body; local execution on this machine is still blocked by the unaccepted Xcode license. |
|
Addressed the Buildkite compile break from the failing skyframe_cluster shard. The failure was in LocalRepositoryLookupFunction: RepoDefinitionFunction.REPOSITORY_OVERRIDES.get(env) needed to propagate InterruptedException, and the new Bzlmod types also needed direct deps on //src/main/java/com/google/devtools/build/lib/bazel/bzlmod:common and //src/main/java/com/google/devtools/build/lib/bazel/bzlmod:module_extension. Pushed in 6caf65e. |
|
@abishekgiri Could you please take a look at the failing checks? |
I traced the failing checks to a shared Skyframe test-fixture issue, not 25 separate failures. The common compile break was that several tests were constructing I pushed a fix in I’m waiting on the fresh Buildkite rerun to confirm the CI side. |
|
@bharadwaj08-one Updated the PR description to Bazel's template and refreshed it to include the follow-up test wiring fix from I also re-ran the focused Skyframe targets locally after that patch: That focused set now passes locally. |
|
I tracked the remaining presubmit failures to repository lookup getting pulled into non-repository paths during package-loading tests. I pushed Local verification now includes:
That broader Skyframe sweep completed successfully on this machine ( |
|
@abishekgiri Thanks, does this change fix #22208? |
|
@meteorcloudy Yes, for the concrete #22208 reproducer, this appears to fix it. I verified it against the original With the repo’s pinned Bazel With the Bazel binary built from this PR ( So for the bug as reported in #22208, this change fixes the reproducer. |
|
@abishekgiri Thanks for checking!
With Bazel@HEAD, --enable_bzlmod is already a no-op, bzlmod is always enabled. So this is expected. |
katre
left a comment
There was a problem hiding this comment.
I have a lot of comments here, but these are mostly just nits and style fixes to make it easier to submit. This is overall a very high-quality change in a very tricky bit of Bazel's code, very well done.
My biggest concern here is the expansion in the number of Skyframe edges due to the extra lookups: my initial read of this (please confirm!) is that this check happens for every subdirectory, which means that in a large monorepo (cough Google's cough) this adds a lot of skytframe edges, which increases memory usage.
(Note: a lot of this is based on my memory of adding the handling for BUILD.bazel files alongside BUILD files back in 2016. Things have changed since then, but even then adding an extra skyframe edge per subdirectory made a big impact.)
However! Last time I saw Google's monorepo, they didn't use local repositories at all. @Wyverald, should we include a flag to disable these checks to use for large monorepos without local repositories?
@Wyverald, regardless of that point, you (or someone with access) absolutely need to run the memory benchmarks on this change. Do we have an open source version? I'm curious what the changes look like just for trying to build Bazel itself. If there's no open source version I may try to cobble something together myself.
| if (rootModuleFileValue == null) { | ||
| return null; | ||
| } | ||
| BazelDepGraphValue bazelDepGraphValue = (BazelDepGraphValue) env.getValue(BazelDepGraphValue.KEY); |
There was a problem hiding this comment.
Instead of doing three env.getValue calls in a row, use getValuesAndExceptions.
| for (RootedPath repoBoundaryPath : repoBoundaryPaths) { | ||
| FileValue fileValue; | ||
| try { | ||
| fileValue = (FileValue) env.getValueOrThrow(FileValue.key(repoBoundaryPath), IOException.class); |
There was a problem hiding this comment.
This is going to do the four (or two, see earlier comment) file lookups in a row, again you should instead use getValuesOrExceptions, and then check those values in the above order.
The only case where that would be a problem would be if this really needs the early-stop behavior: with this implementation, if directory/MODULE.bazel exists, then this never checks for directory/REPO.bazel, and so there's no extra Skyframe edge to that node. There's a benefit there (less memory use for that node), but the semantics are slightly different.
| ImmutableList.of( | ||
| rootedPath(directory, LabelConstants.MODULE_DOT_BAZEL_FILE_NAME), | ||
| rootedPath(directory, LabelConstants.REPO_FILE_NAME), | ||
| rootedPath(directory, LabelConstants.WORKSPACE_DOT_BAZEL_FILE_NAME), |
There was a problem hiding this comment.
Given that in bazel 9 and later, workspace is entirely disabled, why check for these? Do you intend to backport this to earlier branches? Even so, no reason to check for WORKSPACE.bazel or WORKSPACE in bazel 9.
| } | ||
|
|
||
| @Nullable | ||
| private static Boolean directoryHasRepositoryBoundary(Environment env, RootedPath directory) |
There was a problem hiding this comment.
I really dislike (and, more importantly, Google's Java style guide really dislikes) using an object Boolean just so this can return null to indicate a Skyframe restart.
I'd prefer either a private enum (with values PRESENT, MISSING, or RESTART?), or borrow from ToolchainResolutionFunction.ValueMissingException and use a custom, private exception from all of these to indicate a restart is needed, and then compute can catch that and return null.
| return false; | ||
| } | ||
|
|
||
| private static RootedPath rootedPath(RootedPath directory, PathFragment relativePath) { |
There was a problem hiding this comment.
Should this be part of RootedPath? Add a TODO comment to possibly move it.
| } | ||
|
|
||
| @Nullable | ||
| private LocalRepositoryLookupValue maybeMatchCommandLineOverrides( |
There was a problem hiding this comment.
All of these maybe methods are returning a null to indicate "no local repo found", correct? This is a bit confusing because skyframe also uses "null" to indicate "skyframe restart needed", so instead of null, return Optional<LocalRepositoryLookupValue> from all of these.
Description
This PR teaches
LocalRepositoryLookupFunctionto recognize visible local repositories instead of always treating workspace paths as the main repository.It now detects repository roots from command-line repository overrides and from Bzlmod local repositories, including
local_path_override,local_repository, andnew_local_repository. The lookup also avoids pulling in Bzlmod and repository graph state for ordinary non-repository directories by first checking for an actual repo boundary file.The follow-up test updates seed the extra precomputed repository state that direct Skyframe evaluators now need for this lookup, refresh the shared Bzlmod root-module fixture for the current
InterimModulebuilder requirements, add the direct deps required by the touched Skyframe test targets, and make the local-repo fixtures create a realMODULE.bazelboundary.Validated locally with:
bazel test //src/test/java/com/google/devtools/build/lib/skyframe:CollectPackagesUnderDirectoryTest --test_output=errorsbazel test //src/test/java/com/google/devtools/build/lib/skyframe/packages:BazelPackageLoaderTest --test_output=errorsbazel test //src/test/java/com/google/devtools/build/lib/skyframe:LocalRepositoryLookupFunctionTest //src/test/java/com/google/devtools/build/lib/skyframe:PackageLookupFunctionTest --test_output=errorsbazel test //src/test/java/com/google/devtools/build/lib/skyframe/... --build_tests_only --test_output=errorsMotivation
Before this change,
LocalRepositoryLookupFunctioncould misclassify visible local repositories as main-repo packages. That meant package lookup could miss the correct incorrect-repository-reference hint for cross-repository label violations.The remaining presubmit fallout came from repository lookup doing too much work for directories that are not repository roots. Checking for a real boundary first keeps those non-repo paths on the normal package-loading path while still surfacing the correct repository hint for actual local repositories.
Build API Changes
No
Checklist
Release Notes
RELNOTES: None