Skip to content

fix: don't materialize rules_python under the remote repo contents cache - #4294

Open
sputt wants to merge 2 commits into
bazel-contrib:mainfrom
sputt:fix/remote-repo-contents-cache-manifest
Open

sputt wants to merge 2 commits into
bazel-contrib:mainfrom
sputt:fix/remote-repo-contents-cache-manifest

Conversation

@sputt

@sputt sputt commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

With --experimental_remote_repo_contents_cache, a module extension or
repository rule that reads a Label makes Bazel copy that whole repo to
disk. The python extension and the pythons_hub repo read
runtimes_manifest.txt this way, so every build materializes
rules_python.

This replaces runtimes_manifest.txt and
runtimes_manifest_workspace.bzl with a single runtimes_manifest.bzl
(MANIFEST_TEXT) loaded directly by both Bzlmod and WORKSPACE mode, and
updates sort_manifest.py to sort runtimes_manifest.bzl in place.

Before: DEBUG: Materializing remote repo @@rules_python+ on every
build. After: no materialization; the same 741 @pythons_hub targets
and an identical versions.bzl. Tested with Bazel 10.0.0rc1 and a
remote cache, querying @pythons_hub//:all from a fresh output base
after a warm-up run.

Tests: the mock module_ctx can't read real files, which is why the
extension tests had a fake default manifest. Since the manifest is now
loaded rather than read, they use the real one, and the fake is removed.
The archive-flavor test passes its own manifest through a new
testing-only _default_runtime_manifest argument.

With `--experimental_remote_repo_contents_cache`, a module extension or
repository rule that reads a Label makes Bazel copy that whole repo to disk.
The `python` extension and the `pythons_hub` repo read
`runtimes_manifest.txt` this way, so every build materializes rules_python.

This loads the same text from `runtimes_manifest_workspace.bzl`
(`MANIFEST_TEXT`), which `runtimes_manifest_workspace_sync_test` already keeps
identical to the `.txt`. The archive-flavor test passes its manifest through a
new testing-only `_default_runtime_manifest` argument, and the now-unused
default manifest mock is removed.
@rickeylev

Copy link
Copy Markdown
Collaborator

Hm, interesting, and a bit confusing.

(1) How can the rules_python bzlmod extension be processed if rules_python isn't available?

(2) Does this effectively mean bzlmod extensions can't read any files without incurring a download of an entire repository?

@sputt

sputt commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

(1) Bazel has a virtual file system that will download the remote files on demand when loading bzl files. All the starlark can work without materializing the whole thing.
(2) Yes absolutely true today. You will see a "materializing" warning when this happens. I think we can fix this in Bazel bazelbuild/bazel#31923

This is a decent change on its own merits, but we can close in favor of a ctx.read(label) change later after my Bazel PR merges if you prefer.

@rickeylev

rickeylev commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

I brought this up in #bzlmod on bazel slack: https://bazelbuild.slack.com/archives/C014RARENH0/p1792553506777879

It turns out bazel will prefetch all .bzl files. So renaming it to runtimes_manifest.bzl (even if its just plain text) would be a hacky way to avoid the later fetch.

Does changing read(path(label)) to just read(label) avoid the problem of materializing the entire rule_python repo? From that conversation, it sounded like the issue is path() currently forces full materialization. read(label) should incur fetching just the single file from the remote cache instead. If so, lets go with that

If not, then:

(1) Whats the minimum version of bazel to get the above behavior? Basically we're going to drop bazel 7 support when bazel 10 comes out, so I'd rather not add it just for bazel 7.

(2) Some variant of this PR SGTM. In that case, the main change in this PR to make is removing the dead code and renaming as appropriate -- runtimes_manifest.txt essentially becomes unused, and runtimes_manifest_workspace.bzl becomes a misnomer.

But either way, there's no avoiding the fetch of the content: either bazel prefetches it due to the .bzl extension, or it gets fetched later when read() is called.

@rickeylev

Copy link
Copy Markdown
Collaborator

does read(label) (no path()) avoid the problem

I checked, it doesn't. There's a pending PR in bazel to allow that, but not in current versions. Ah well. Yeah, lets move it all to the .bzl file as a string for now, then.

Now that both Bzlmod and WORKSPACE mode load `MANIFEST_TEXT` from Starlark
instead of reading `runtimes_manifest.txt`, keeping both files and a sync
script is redundant.

Replace `runtimes_manifest.txt` and `runtimes_manifest_workspace.bzl` with
`runtimes_manifest.bzl`, remove `sync_runtimes_manifest_workspace.py`, and
update `sort_manifest.py` to sort `runtimes_manifest.bzl` in place.

This branch has not been deployed

No deployments
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.

3 participants