build(tooling): run the hooks with prek and manage Python deps with uv - #350
Merged
Conversation
Minipada
force-pushed
the
chore/prek-uv-migration
branch
3 times, most recently
from
August 17, 2026 18:07
9195be0 to
95ea6b1
Compare
Mirrors the move already made in ~/dev/monorepo. .pre-commit-config.yaml is now
run by prek -- same file, same schema, one Rust binary that resolves hook
environments with uv and needs no Python environment of its own -- and
dependencies live in a PEP 621 pyproject.toml + uv.lock instead of poetry.
The formatting job was dead, not slow: it installed poetry and then pip-installed
requirements.txt + requirements-dev.txt just to get pre-commit on PATH, and that
install has been failing outright ("Failed to build 'fastcov' ... No module named
'pkg_resources'"), so the last two runs never reached a hook. It now installs
prek and nothing else -- no apt step either.
Python lint/format becomes ruff only: flake8 + 13 plugins, black, isort, pycln,
pyupgrade, flynt, yesqa and python-no-log-warn are gone, and [tool.ruff.lint]
selects for parity with what they enforced rather than for maximum strictness.
Fixing the fallout is most of this diff -- 16 lint findings and 14 files
reformatted, plus two failures the broken job had been hiding: dc_triggers' two
.cpp files were never clang-formatted, and tools/e2e/Containerfile's
`find | xargs` tripped hadolint DL4006/SC2038.
requires-python moves to >=3.12 (Jazzy), with numpy and pydantic deliberately
held below 2 -- rclpy/cv_bridge are built against numpy 1.26, and draw_image.py
and the dashboard still use pydantic v1 APIs. requirements.txt and
requirements-dev.txt are deleted rather than re-exported: pyproject.toml +
uv.lock are the one dependency source, and the docs now say `uv sync`.
minipada/ros2_pre-commit's two checks are vendored to
tools/ci/pre-commit/ros2_package_checks.py: upstream's unbounded
`find -name setup.py` walks into the ./.venv uv sync creates and checks numpy's
setup.py against the DC version, and both hooks shell out to xmllint, which the
runner image doesn't ship. Reading package.xml with ElementTree -- the parser the
check-xml hook already uses -- is what leaves this job with no system
dependencies at all.
CLAUDE.md gains a Comments rule (headers one to three lines, why not what, long
rationale in progress.txt or the PR), prompted by this branch's first draft of
format.yaml carrying a 22-line header essay.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015aZ8Ng8bK4mK9keCKxPzwX
Signed-off-by: David Bensoussan <d.bensoussan@proton.me>
Minipada
force-pushed
the
chore/prek-uv-migration
branch
from
August 17, 2026 18:09
95ea6b1 to
78a3fbc
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## jazzy #350 +/- ##
==========================================
- Coverage 67.55% 67.54% -0.00%
==========================================
Files 95 95
Lines 5885 5884 -1
==========================================
- Hits 3975 3974 -1
Misses 1910 1910
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Mirrors the move already made in
~/dev/monorepo:.pre-commit-config.yamlis now run by prek — same file, same schema, one Rust binary that resolves hook environments with uv and needs no Python environment of its own — and dependencies live in a PEP 621pyproject.toml+uv.lockinstead of poetry's[tool.poetry]+poetry.lock.No issue for this one; it came out of the observation that the formatting gate had stopped running at all.
The formatting job was dead, not slow
.github/workflows/format.yamlinstalled poetry and then pip-installedrequirements.txt+requirements-dev.txtjust to getpre-commiton PATH. That install had been failing outright —ERROR: Failed to build 'fastcov' … ModuleNotFoundError: No module named 'pkg_resources'— so its last two runs never reached a single hook, and the workflow was then disabled manually. Every finding below is therefore pre-existing drift the dead gate was hiding, not new. (The workflow is enabled again as of this PR, which is where it is first exercised: 24 hooks, 25 seconds.)The job now installs prek and nothing else: no poetry, no pip, no apt. clang-format arrives in the mirror hook's own wheel,
check-xmluses Python's parser rather thanxmllint, and graphviz was only ever there forpydeps, which nothing calls.Python lint/format is ruff only
flake8 + 13 plugins, black, isort, pycln, pyupgrade, flynt, yesqa and the
python-no-log-warnpygrep hook are replaced byruff-check+ruff-format— one binary instead of ~20 hook environments pre-commit had to build before linting a line.[tool.ruff.lint]'s selection is chosen for parity with what the old stack enforced (E/W/F,I,UP,B,C4,A,Q,N,G/LOG,T10,EXE, andRUF100for yesqa), not for maximum strictness: ruff's newer opinions (the rest ofRUF,SIM,PTH, …) are deliberately left off, the same "broaden over time" stance the monorepo's first rollout took.setup.cfg's[flake8]/[darglint]sections are gone; darglint has no ruff equivalent worth turning on blind and is not replaced.Fallout, all mechanical, fixed rather than ignored: 16 findings from the parity rule set (unsorted imports, a stale
# noqa: T201×3 for a rule this repo never enabled,datetime.utcnow, three(str, Enum)classes →StrEnum, two barezip()s →strict=True, three root-logger calls in the dashboard → a module logger, one dict comprehension) and 14 files reformatted by ruff-format (mostly black 23's missing blank line after a module docstring). Two more the dead job had hidden:dc_triggers' two.cppfiles were never clang-formatted, andtools/e2e/Containerfile'sfind … | xargstripped hadolint DL4006/SC2038 — rewritten asfind … -exec … +, which drops the pipe instead of silencing the rule.Dependencies
requires-pythonmoves from the humble-era>=3.8.10,<3.9.7 || >3.9.7to>=3.12(Jazzy/Ubuntu 24.04), with.python-versionpinning 3.12 so a localuv syncbuilds against the interpreter the code actually runs on. Deliberately held below 2: numpy (Jazzy's rclpy/cv_bridge are built against 1.26) and pydantic (draw_image.pyand the dashboard still use v1 APIs —BaseSettings).Dropped from the dev group as used by nothing:
ipython,pydeps,pylint,cmake-format, plusstrictdocandfastcov, which live in the containers that actually run them (containers/doc/Containerfile,tools/e2e/Containerfile) —fastcov's sdist is what broke CI in the first place.requirements.txtandrequirements-dev.txtare deleted, not re-exported:pyproject.toml+uv.lockare the single dependency source, and a generated copy in the tree is only somewhere for the two to disagree.doc/src/dc/setup.mdand the two AWS demo pages now sayuv sync(--no-devfor the runtime set alone), and.dockerignoreallowspyproject.toml+uv.lockin their place.The ROS manifest hooks are vendored
minipada/ros2_pre-commit'sros2_ws_same_versionsfinds setup.py with an unboundedfind "$SRC" -name setup.py, so onceuv syncputs a virtualenv at./.venvit checks every setup.py in site-packages — numpy's, for one — against the DC version. Both its hooks also shell out toxmllint, which GitHub's runner image doesn't ship, and that was the only system dependency left in the whole hook set.tools/ci/pre-commit/ros2_package_checks.pydoes both checks overdc_*/only (versions: one version across everypackage.xmland eachdc_*/setup.pydeclaring it;metadata: no package left the template's placeholder license, maintainer or description), reading manifests withElementTree— the same parser thecheck-xmlhook already uses. stdlib rather than defusedxml: the input is this repo's own manifests, and the dependency would mean giving the hook a Python environment it otherwise doesn't need.Also: a comments rule in CLAUDE.md
File headers one to three lines, block comments one or two, why not what, long rationale in
progress.txt/ an ADR / the PR description. Prompted by this branch's first draft offormat.yaml, which carried a 22-line header essay.ci.yaml,doc.yamlandtools/e2e/Containerfilepredate the rule — to be trimmed when next touched, not copied.Verification
Formatting (prek)passes on this PR — all 24 hooks in 25s, hadolint's docker-image hook included.prek run --all-files --skip build-docpasses locally too (addsbuild-doc, whichdoc.yamlowns in CI).uv sync --frozenresolves and installs on 3.12; every dev-group and runtime package imports, andrufffrom that venv is the same 0.16.3 the hook pins..pyfiles byte-compile.check_if_numbers_are_consecutiveand the dashboard's threeStrEnums were smoke-tested directly (.value,==against a plainstr, and iteration order all unchanged).package.xmlversion, a mismatchedsetup.pyversion and a package with all three placeholder fields are each reported, and both checks pass once the workspace agrees (single-quotedversion='…'included, which upstream'sgrepdid not accept).🤖 Generated with Claude Code
https://claude.ai/code/session_015aZ8Ng8bK4mK9keCKxPzwX