Bazel rules for running Pyrefly type
checking over py_* targets.
rules_pyrefly is an experimental integration for pyrefly bazel-check. It can
run Pyrefly through a registered Bzlmod toolchain or through a direct
pyrefly_cli executable override.
Pyrefly 1.2.0 is the checked-in supported version and the first stable Pyrefly
release that includes the experimental bazel-check command.
For more detail, see the design, integration notes, and user notes.
Add the ruleset and register a Pyrefly toolchain in MODULE.bazel:
bazel_dep(name = "rules_pyrefly", version = "<version>")
pyrefly = use_extension("@rules_pyrefly//pyrefly:extensions.bzl", "pyrefly")
pyrefly.toolchain(version = "1.2.0")
use_repo(pyrefly, "pyrefly_toolchains")
register_toolchains("@pyrefly_toolchains//:all")The selected Pyrefly version must either be present in the ruleset's checked-in
release metadata or be supplied with explicit release asset checksums. Use
base_url with checksums for forks, mirrors, or prereleases outside the default
Pyrefly GitHub release location.
Define an aspect in a project-local .bzl file:
load("@rules_pyrefly//pyrefly:pyrefly.bzl", "pyrefly")
pyrefly_aspect = pyrefly()Register it in .bazelrc:
build:pyrefly --aspects=//tools:aspects.bzl%pyrefly_aspect
build:pyrefly --output_groups=pyreflyThen run:
bazel build --config=pyrefly //...Use --output_groups=+pyrefly only when you also want Bazel to build the
targets' normal outputs. For type-check-only runs, --output_groups=pyrefly
keeps unrelated build failures out of the Pyrefly pass.
The default aspect infers the target Python version from the active
rules_python toolchain and the target platform from Bazel platform
constraints. Pass python_version or system_platform only when that inference
is not enough for a workspace.
The pyrefly() aspect factory accepts these options:
| Option | Default | Purpose |
|---|---|---|
pyrefly_cli |
Registered toolchain | Executable override supplied as a Label. |
python_version |
Inferred | Target Python version, such as "3.12". |
system_platform |
Inferred | Target sys.platform value, such as "linux", "darwin", or "win32". |
preset |
Unset | Pyrefly preset passed to bazel-check. |
min_severity |
"error" |
Minimum reported severity: "ignore", "info", "warn", or "error". |
error_severities |
{} |
Per-error-kind severity overrides. |
suppression_tags |
["no-pyrefly"] |
Target tags that disable checking. |
opt_in_tags |
[] |
When nonempty, target tags that enable checking. |
color |
"always" |
Diagnostic color mode: "auto", "always", or "never". |
error_severities maps Pyrefly error-kind names to the same four severity
values accepted by min_severity. Suppression tags take precedence over opt-in
tags. For example:
pyrefly_aspect = pyrefly(
color = "auto",
error_severities = {"bad-assignment": "error"},
min_severity = "warn",
suppression_tags = ["no-pyrefly", "no-checks"],
)Use pyrefly_cli when testing a local or otherwise preinstalled Pyrefly binary:
pyrefly_aspect = pyrefly(
pyrefly_cli = Label("@local_pyrefly//:pyrefly"),
)The aspect follows the rules_python python_import_all_repositories setting
when it builds repository-root search-path facts for Pyrefly.
Generated pyrefly bazel-check input JSON files are available through the
debug-only pyrefly_input output group.
The demo workspace consumes this repository through local_path_override:
cd examples/demo
bazel build --config=pyrefly //...The demo includes //:type_error, a manual target with an intentional type
error:
bazel build --config=pyrefly //:type_errorTo test a local Pyrefly binary instead of the release toolchain, create a Bazel
repository that exposes the binary as a public executable target named
//:pyrefly, then inject it as @local_pyrefly:
bazel build \
--inject_repository=local_pyrefly=/path/to/local_pyrefly \
--aspects=//:aspects_local.bzl%pyrefly_aspect \
--output_groups=pyrefly \
//...Common checks:
bazel build //...
bazel run @buildifier_prebuilt//:buildifier -- -mode=check -r .
python tests/verify_demo.pyToolchain resolution coverage downloads release assets and needs BCR and GitHub release access:
python tests/verify_toolchain_resolution.py
python tests/verify_toolchain_resolution.py --output-group=pyreflyThe first command checks generated input JSON without executing the downloaded
Pyrefly binary. The second command exercises the real bazel-check action path.
rules_pyrefly is Apache 2.0 licensed. See LICENSE and
CODE_OF_CONDUCT.md.