Development¶
Contributions are welcome through pull requests on GitHub.
Layout¶
Path |
What |
|---|---|
|
The toolkit: model, validation, ingestion, tracing, reports, hooks, CLI. |
|
Vendored PyYAML (pure-Python part, MIT). |
|
Unit tests (pytest). |
|
Bazel rules and macros. |
|
googletest hook. |
|
Per-case JUnit for plain-assert C++ tests. |
|
Rust hook crate ( |
|
node:test runner behind |
|
JSON Schema for model files. |
|
Every hook → evidence → report, pinned by goldens. |
|
|
|
Analysis tests of |
|
The Tutorial: a requirements-first thermostat project (a separate Bazel module). |
|
This site. |
Python tests and coverage¶
$ pip install -e ".[test]"
$ pytest
$ coverage run -m pytest && coverage report
Measure coverage with coverage run rather than pytest --cov: the installed
package registers a pytest11 plugin, which pytest imports before pytest-cov
starts measuring. CI requires at least 90 % line and branch coverage.
Bazel¶
$ bazel test //... # unit tests + hook integration goldens
$ (cd examples/thermostat && bazel test //...)
The root module and the example are separate Bazel modules (.bazelignore
keeps examples/ out of the root). Local settings — an output base, a disk
cache — belong in an untracked user.bazelrc, which .bazelrc imports if it
exists.
The unit tests run under Bazel with their own pip hub, rr_dev_pip, locked in
python/requirements_dev.lock; regenerate it with
bazel run //python:requirements_dev.update.
When a change intentionally alters a report, regenerate the goldens and review the diff:
$ bazel run //tests/integration:report_json_golden_test.update
$ bazel run //tests/integration:report_md_golden_test.update
$ bazel run //tests/node:cases_golden_test.update
$ bazel run //tests/integration:rr_case_report_json_golden_test.update
$ bazel run //tests/integration:rr_case_report_md_golden_test.update
$ bazel run //tests/integration:rr_case_lock_test.update
(and the same targets in examples/thermostat).
python/tests/fixtures/migrate/ is a small source tree for rr migrate: test
sources with multi-id tags, their evidence, a decided worksheet, and under
expected/ the worksheet renderings and the rewritten sources the tests
compare against. Regenerate those with
RR_UPDATE_FIXTURES=1 python -m pytest python/tests/test_migrate.py python/tests/test_tag_codemod.py.
Presubmit checks¶
$ pip install pre-commit && pre-commit run --all-files
Hook |
Checks |
|---|---|
pre-commit-hooks |
trailing whitespace, final newlines, YAML/JSON/TOML syntax, merge conflicts, large files, LF line endings |
ruff |
lint and formatting ( |
mypy |
strict type checking of |
buildifier |
formatting and lint of Starlark |
codespell |
spelling |
SPDX header |
every first-party source file starts with |
Continuous integration¶
ci.yaml runs on every push and pull request:
Lint — the presubmit checks above.
Python 3.9–3.13 — the unit tests, and the coverage gate.
node:test conformance —
rr_node_test’s runner on Node 18 (the fallback), 20, 22 and 24 (python/tests/test_node_runner.py), so a change in node:test’s event model fails here rather than in a consumer.Bazel —
bazel test //...with Bazel 7.7.1 and 8.8.1 on Linux, and 8.8.1 on macOS.Example — the thermostat’s tests and report with Bazel 7.7.1 and 8.8.1; the rendered report is uploaded as an artifact.
Python package — builds the wheel and smoke-tests it in a clean environment.
docs.yaml builds this site on every push and pull request; on main it also
measures coverage for the badge and publishes the site to GitHub Pages.
Documentation¶
$ pip install -r docs/requirements.txt -e .
$ python tools/docs_build.py -W -n --keep-going -b html docs docs/_build/html
tools/docs_build.py runs Sphinx and also fails on any docutils WARNING/
line or rendered problematic node, which -W misses when docutils prints
them outside Sphinx’s logger (a --help text that is not clean
reStructuredText, say). The pages are MyST Markdown. The CLI reference is generated from the argument
parser and the API reference from docstrings; the trace graphs are drawn at
build time by the toolkit itself.
License¶
rules_requirements is licensed under the
GNU Affero General Public License v3.0 or later.
The vendored copy of PyYAML is distributed under its MIT license
(python/rules_requirements/_vendor/yaml/LICENSE).