Modernise our lint tooling by:
- Replacing pyenv + pip with uv for better Python environment and dependency management
- Replacing mypy with https://github.com/astral-sh/ty
- Move uv ruff and ty to install via COPY --from multi-stage Docker image imports
- Moving ruff lint rules from hardcoded Rust array (in lint_py.rs) into a top-level ruff.toml, and add ty.toml for the type checker
- Extracting all remaining pip dependencies into dedicated ci/lint/requirements.txt
Extra rationale:
COPY --from pulls pre-built binaries from upstream images instead of compiling/downloading at runtime. Containerfile layer optimisations reduce rebuild frequency further.
ty is significantly faster/more modern/maintained than mypy, and configured declaratively.
Adding root-level [ty|ruff].toml config files means contributors can easily run ty check or ruff check locally without running the full linter, along with being accessible to other tooling (similarly for requriements.txt).
Pinning tool versions in the dockerfile makes it more excplicit and easier to find.
The tradeoff we make here is that there is no longer a single install script to install tooling on a local machine. However I think this is OK, as it currently only works for apt-based OSes anyway, and I don’t think running the linter outside of the container is such a valuable use-case as it is with some of the other CI jobs.
Further work can drop individual rules from ty.toml fixing up the infringing code as necessary. Whilst we have ignore rules in ty.toml then certain things may go undetected (as they are ignored), and this may be a temporary regression against master using mypy, until the infracting code is fixed and the rule can be un-ignored.