Skip to content

refactor(toolchains): register runtimes using manifest#3812

Merged
rickeylev merged 58 commits into
bazel-contrib:mainfrom
rickeylev:register-builtin-runtimes-manifest
Jun 14, 2026
Merged

refactor(toolchains): register runtimes using manifest#3812
rickeylev merged 58 commits into
bazel-contrib:mainfrom
rickeylev:register-builtin-runtimes-manifest

Conversation

@rickeylev

@rickeylev rickeylev commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

This changes the list of runtimes that are registered to come from a file instead of
being logic within Starlark code.

Along the way...

  • Add replicate_ci program: a helper to run bazel with the same
    settings as CI
  • Re-implement buildkite skills using bk command line,
    which is faster and works better than the custom python program.
  • Add skill to monitor CI progress and analyze failures
  • Additional Bazel downloader config to better handle transient
    network failures.
  • Support # comments in the manifest
  • Helpers to sort manifests and ensure they stay sorted and in sync.

rickeylev added 10 commits May 31, 2026 21:10
Currently, all supported Python runtime versions and their
platform-specific metadata (URLs, SHA256s, strip_prefix) must be
hardcoded in `python/versions.bzl`. This makes it slow and difficult
to adopt new Python versions or custom builds without updating
`rules_python` itself.

This PR introduces the ability to dynamically fetch and register
Python runtimes from a remote python-build-standalone (PBS) manifest
file (e.g., `SHA256SUMS`).

This is supported via two new attributes in `python.override`:
- `add_runtime_manifest_urls`: A list of URLs pointing to manifest
  files to parse and register.
- `runtime_manifest_sha`: The SHA256 hash of the manifest file.
…ce mode

Workspace builds running under older Bazel versions do not support Bzlmod module
extensions. This commit introduces Starlark helper macros to conditionally gate
and register Bzlmod-specific unit tests, resolving test suite loading crashes in
workspace CI jobs.
Removes the external test_helpers.bzl under tests/python/ and inlines the
register_python_tests macro directly inside python_tests.bzl. This simplifies
the test suite layout while keeping legacy workspace gating completely intact.
Enables local PBS manifest file resolution in Bzlmod mode.
Implemented attr.label_list attribute on python.override and updated
_populate_from_pbs_manifest to read local files via module_ctx.read.
Separates free-threading and archive type from the build flavor string
in parse_filename. Also includes canonical documentation citation in
the docstring and updates manifest parsing assertions.
Documents local manifest file loading alongside remote manifest URLs.
Includes unified Starlark example using @// label prefix.
Flattens parsed manifest entries into a single list and sorts by
archive flavor (install_only > install_only_stripped > full) so
smaller standalone archives take precedence.
Restores explicit whitelist validation on entry.archive_flavor
to prevent unsupported standalone release asset formats from
polluting available toolchain mappings.
# Conflicts:
#	tests/support/mocks/python_ext.bzl
Centralizes standalone Python runtime asset registration into python/runtimes_manifest.txt and parses it dynamically via _populate_from_pbs_manifest, replacing the static TOOL_VERSIONS table.
@rickeylev rickeylev requested a review from aignas as a code owner June 6, 2026 18:38
@rickeylev rickeylev added the do not merge Tag that prevents merging label Jun 6, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for dynamically fetching and registering Python runtimes from a python-build-standalone manifest file, replacing the hardcoded TOOL_VERSIONS map with a dynamic parser. Feedback on the implementation highlights several critical Starlark compatibility issues, such as the unsupported use of lambda expressions and string methods like removeprefix and removesuffix on older Bazel versions. Additionally, suggestions are provided to improve robustness by handling empty base download URLs, parsing tabs in manifests, and fixing a potential type error in the test suite.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread python/private/python.bzl
Comment thread python/private/pbs_manifest.bzl
Comment thread python/private/pbs_manifest.bzl
Comment thread python/private/pbs_manifest.bzl
Comment thread python/private/python.bzl
Comment thread python/private/pbs_manifest.bzl
Comment thread tests/python/python_tests.bzl Outdated
@rickeylev

Copy link
Copy Markdown
Collaborator Author

I really like this listing of it. It makes it really obvious and apparent how many runtimes are being registered (600+ !). It also just seems much easier to add/remove entries.

The paths in the manifest are a bit funny: <DATE>/<filename>. This is somewhat expected because we're mixing and matching across different build dates.

It looks like CI is failing on the workspace tests. I'm not keen to port all this functionality to workspace. I'm thinking, for workspace, we just replace some internals so it reads from the manifest file, but don't expose a add_runtime_manifest_{file,url} equivalent.

Q: Should we have one manifest file, or split it along some axis? e.g. python version, platform, build date, etc.

Q: Should we publish a runtime manifest as part of releases? The thought is it lets one easily "upgrade" the runtimes (treating rules_python as a trusted source) without having to upgrade rules_python itself. The counter argument is: one can always add a custom manifest.

rickeylev added 3 commits June 7, 2026 08:30
	Instead of generating complex nested Starlark dictionaries during repository
	setup, internal_config_repo now generates a straightforward list of parsed
	manifest structs (MANIFEST_ENTRIES) using render.struct() and render.list().
	The versions.bzl module dynamically converts these entries into the legacy
	TOOL_VERSIONS dictionary format when loaded during macro evaluation.
…times-manifest

# Conflicts:
#	tests/python/python_tests.bzl
	Update internal_config_repo_bzl and python_register_toolchains_bzl in
	python/private/BUILD.bazel to include their respective loaded modules
	so that Stardoc extracts API documentation successfully.
rickeylev added 2 commits June 9, 2026 06:38
…flags

	Mitigate transient 504 Gateway Timeout network errors during downloads by
	adding secondary mirror fallback rewrites for Stardoc to downloader_config.cfg
	and scaling HTTP timeouts and retries in .bazelrc files.
@rickeylev rickeylev requested a review from dougthor42 as a code owner June 9, 2026 06:52
rickeylev added 6 commits June 9, 2026 06:54
	Combat transient 504 Gateway Timeout network dropouts on external artifact
	downloads by escalating HTTP timeout scaling to 10.0 and downloader retries
	to 10 across bazelrc files, and adding a mirror rewrite rule for rules_java.
	Ensure primary GitHub release URLs are attempted prior to secondary mirror
	fallbacks by adding primary pass-through rewrite rules for rules_java and
	stardoc across downloader_config.cfg files.
Sets `python_version = "3.14"` directly on `sphinx_build_binary` to ensure
the documentation builder executes with a modern Python runtime capable of
parsing PEP 695 type aliases in recent Sphinx releases.
Replaced fragile substring search over PLATFORMS.keys() with direct
synthesis of the PLATFORMS dictionary key from structured struct fields
(arch, vendor, os, libc, freethreaded). Eliminated defensive getattr()
access. Factored entry sorting into _manifest_entry_sort_key preferring
install_only and the lowest microarchitecture level.
…ntimes-manifest

# Conflicts:
#	python/private/pbs_manifest.bzl
#	python/private/python.bzl
Renamed flavor to build_flavor in parse_filename and parse_sha_manifest
to clearly distinguish runtime build configurations (e.g., debug, pgo+lto)
from distribution release bundling schemes (archive_flavor).
@rickeylev rickeylev removed the do not merge Tag that prevents merging label Jun 9, 2026
Comment thread python/versions.bzl Outdated
Comment thread python/runtimes_manifest.txt Outdated
…on releases

Adds all prior release distribution entries (including historical Python 3.8-3.13 and freethreaded variant builds) to runtimes_manifest.txt to ensure dynamic runtime registration provides equivalent toolchain coverage to the previous static table.
rickeylev added 12 commits June 13, 2026 07:12
Adds .agents/skills/monitor-ci-results containing continuous background polling and log analysis support scripts. Allows developers and automated agents to autonomously watch GitHub checks and Buildkite workflow executions for a PR, downloading full logs and reporting actionable resolution plans upon any failure.
…itories

Removes the deprecated workspace_mode parameter from the internal_config_repo repository rule call inside python/private/py_repositories.bzl. Fully restores compatibility for legacy WORKSPACE macros across example and downstream projects.
Updates monitor_remote_ci.py to inspect job exit_status in addition to job state, correctly catching failures where Buildkite marks job state as 'finished'.
Enhances monitor_remote_ci.py to compute and display real-time summary counters (passed, failed, running, other) and log all discovered Buildkite job IDs across each polling cycle.
Removes individual job ID print statements from monitor_remote_ci.py to keep polling logs clean and streamlined. Retains the one-line Buildkite swarm summary breakdown (passed, failed, running, other).
Extracts and displays the underlying Buildkite Build ID / number alongside the Passed/Failed/Running swarm counters to clearly anchor active polling progress in the logs.
Streamlines the Buildkite summary line prefix to exactly 'Buildkite #{build_id}:' per user code review comment, improving log scan readability.
…lure skill

Creates the analyze-ci-failure skill and migrates analyze_ci_failure.py out of monitor-ci-results. Updates monitor_remote_ci.py to only dispatch lightweight failure alerts rather than performing heavy log downloading and analysis itself. Also configures the monitor to ignore upstream rolling Bazel CI job incompatibilities.
Replaces the hardcoded 'rolling' job filter with an architectural inspection of the 'soft_failed' attribute in Buildkite metadata. Ensures that jobs allowed to fail are correctly categorized as passed/ignored rather than triggering failure alerts. Also removes cached runtime log artifacts from repository tracking.
Regenerates tests/integration/bzlmod_lockfile/MODULE.bazel.lock to reflect underlying Starlark implementation changes in rules_python extensions. Resolves integration test verification failures under lockfile_mode=error.
…starting a subagent

Refines the alert text dispatched by monitor_remote_ci to explicitly prompt the recipient to invoke a subagent for failure analysis, supporting fully agentic background delegation.
…legation prompts

Adopts an exact imperative phrasing ("Start subagent: run analyze-ci-failure skill on this failure") in the failure alerts dispatched by monitor_remote_ci per direct code review instructions.
@rickeylev

Copy link
Copy Markdown
Collaborator Author

woo, success!

I need to do some cleanup (later, its 1am), but this is finally passing.

For the workspace problem: I just embedded a duplicate of runtimes_manifest.txt as a bzl file so it's easy to load. I don't want to put a lot of effort into workspace mode. Maybe a future change could add the ability to use custom manifests that get parsed at repo phase.

…scripts

Adds an absolute rule to AGENTS.md prohibiting the addition of Bazel copyright headers to new or existing files per user directives. Also purges existing Bazel copyright headers from our newly created analyze_ci_failure.py and monitor_remote_ci.py scripts.
Comment thread tests/support/mocks/mocks.bzl Outdated
Comment thread tests/toolchains/transitions/transitions_tests.bzl Outdated
…e reviews

Refactors the runtimes manifest landscape by moving the catalog into python/private/ and establishing canonical automated synchronization tools (sort_manifest.py, sync_runtimes_manifest_workspace.py). Renames legacy manifest parsers to parse_runtime_manifest, privatizes internal tool logic, scrubs generic test mocks of hardcoded manifests, and reinforces the core diff and transition suites.
Comment thread gazelle/downloader_config.cfg Outdated
Comment thread gazelle/downloader_config.cfg Outdated
Comment thread python/private/python.bzl
Comment thread python/runtimes_manifest.txt Outdated
Comment thread python/runtimes_manifest.txt Outdated
Comment thread python/versions.bzl Outdated
Comment thread python/versions.bzl Outdated
Comment thread tests/support/mocks/mocks.bzl Outdated
Comment thread tests/toolchains/transitions/transitions_tests.bzl Outdated
Comment thread python/private/print_toolchain_checksums.bzl Outdated
Updates runtime_manifests_tests.bzl to use python_ext.mctx instead of mocks.mctx to ensure the default runtimes manifest is available during test analysis.
…tests

Adds macos execution platform constraints to py_exec_tools_toolchain test rules and splits flag transition tests into driver and consumer rules to ensure Bazel 10 toolchain resolution propagates correctly.
…ark rule

Removes print_toolchains_checksums from python/private/BUILD.bazel and purges print_toolchain_checksums.bzl as it is legacy functionality replaced by the public TOOL_VERSIONS map.
…guration

Renames base_url attribute to base_urls on module extension override tags and defaults to provide multi-mirror download fallback. Outfits get_release_info with DEFAULT_RELEASE_BASE_URLS (GitHub astral-sh, releases.astral.sh, indygreg) to guarantee duplicate-free fallback resolution across all registered runtimes.
Enforces LF line endings on runtimes manifest files in .gitattributes and ensures sync_runtimes_manifest_workspace writes output files with LF to prevent checkout mismatches during Windows CI diff testing.
…mat links

Adds entry to CHANGELOG.md explaining bzlmod runtimes manifest registration and adds seealso links to manifest file format docs in python.override add_runtime_manifest attributes.
@rickeylev

Copy link
Copy Markdown
Collaborator Author

FYI: This also adds several skills. I had pretty good results with them (it successfully fetched, diagnosed, reproduced, and fixed several CI failures on the first try and without going off the rails)

@rickeylev rickeylev added this pull request to the merge queue Jun 14, 2026
Merged via the queue into bazel-contrib:main with commit 99d0c3d Jun 14, 2026
5 checks passed
@rickeylev rickeylev deleted the register-builtin-runtimes-manifest branch June 14, 2026 03:37
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