Skip to content

CI: enforce ty type-checking + pre-commit config (ruff + ty)#125

Merged
neuromechanist merged 4 commits into
mainfrom
119-ci-enforce-ty-type-checking-+-add-pre-commit-config-ruff-+-ty
Jul 14, 2026
Merged

CI: enforce ty type-checking + pre-commit config (ruff + ty)#125
neuromechanist merged 4 commits into
mainfrom
119-ci-enforce-ty-type-checking-+-add-pre-commit-config-ruff-+-ty

Conversation

@neuromechanist

Copy link
Copy Markdown
Member

Summary

Closes #119. Enforces ty type-checking in CI and adds a .pre-commit-config.yaml
with ruff + ty hooks. Unblocked by #122 (repo is now at 0 ty diagnostics), so
ty check lands as a hard gate (option (a) from the issue), not informational.

Changes

  1. ty + pre-commit pinned in the dev group (pyproject.toml + uv.lock).
    ty was only available locally via Homebrew, so CI's ubuntu runner had no type
    checker at all. Pinning both means uv sync provides the same versions in CI,
    locally, and in the hook (ty 0.0.59, pre-commit 4.x).

  2. CI typecheck job (.github/workflows/ci.yml): a new Type check (ty)
    job runs uv run ty check . on the plain base env. test and build now
    needs: [lint, typecheck], so a type error fails fast before the ~10-min test
    run. Added as its own job (not folded into lint) so it surfaces as a distinct
    status without renaming the existing Lint (ruff) check.

  3. .pre-commit-config.yaml: local hooks running ruff + ty through uv,
    so versions track pyproject/CI with no pre-commit-mirror drift.

    • ruff check --fix --unsafe-fixes + format on staged Python files.
    • ty check . whole-project (pass_filenames: false): type errors are
      inherently cross-file, so per-file checking is unsound; ty is fast enough
      (Rust, sub-second here) to re-check everything each commit. Fires only when a
      Python file is staged, and runs the identical command to the CI job, so a
      green pre-commit implies a green CI gate.
  4. Scoped # ty: ignore[unresolved-import] on the two lazy mne imports in
    benchmarks/benchmark_decompose.py. mne is the optional viz extra, absent
    from the base env; this matches the existing mlx treatment and keeps
    ty check . clean on the base env (so every dev and the hook see 0 diagnostics
    without installing optional extras), rather than coupling the gate to --extra viz.

Design notes

  • Why whole-project ty in the hook (a deliberate deviation from the issue's
    "staged files only" for ty specifically): a type checker that only sees staged
    files misses errors an edit introduces in other files. ruff (a fixer) stays
    staged-only where scoping actually matters. The whole-project ty run is cheap.
  • Optional deps stay ignored, not installed: mlx (Apple-only) can never
    resolve on Linux, and mne (viz extra) would need a heavier CI env and still
    leave local ty check . dirty for anyone without the extra. Scoped inline
    ignores keep the base-env check honestly clean and the gate simple.

Validation

  • uv run ty check . -> All checks passed! (0 diagnostics, base env)
  • uv run pre-commit run --all-files -> ruff-check / ruff-format / ty all Passed
  • uv run ruff check / ruff format --check clean
  • pytest test_decompose_equiv.py green (only Python change is the two comments)

ty was only available locally via Homebrew, so CI's ubuntu runner had no
type checker. Pin ty and pre-commit in the dev group (updating uv.lock) so
`uv sync` provides them deterministically in CI, locally, and in the hook.

mne is the optional 'viz' extra, absent from the base env; add scoped
`# ty: ignore[unresolved-import]` to its two lazy imports (matching the mlx
treatment) so `ty check .` is clean on the plain base env without pulling
optional extras -- the foundation for the CI gate and pre-commit hook.
New 'Type check (ty)' job runs 'uv run ty check .' on the base env; test
and build now need [lint, typecheck] so a type error fails fast before the
~10-min test run.
Local hooks run ruff (check --fix + format, staged files) and ty (whole
project, since type errors are cross-file) through uv, so versions match
pyproject/CI with no mirror drift. Install with: uv run pre-commit install.
@neuromechanist neuromechanist linked an issue Jul 14, 2026 that may be closed by this pull request
Address PR #125 review: ty is version-locked via uv.lock (pyproject uses a
lower bound), and note uv sync as a prerequisite for pre-commit install.
@neuromechanist

Copy link
Copy Markdown
Member Author

/review-pr summary (2 Sonnet reviewers: code + comments)

No Critical or Important findings. Both reviewers verified the CI + pre-commit wiring end-to-end (locally ran uv sync, ty check ., pre-commit run --all-files; cross-checked live CI where the new Type check (ty) job passed in ~26s and test/build correctly waited on needs: [lint, typecheck]).

Confirmed correct: the acyclic needs graph, paths-ignore skipping the whole workflow (incl. typecheck) for docs-only changes as before, valid .pre-commit-config.yaml (all three hooks execute; pass_filenames: false on ty runs whole-project as intended), ty/pre-commit present in uv.lock, the mne ty: ignore scoping matching the existing mlx treatment, and UV-only / no-emoji / no-AI-attribution compliance. Comment reviewer verified every new comment is factually accurate (mne = viz extra, mlx = Apple-only, hook entry byte-identical to the CI step, #119 is the right issue, sub-second ty runtime measured).

Addressed (minor precision nits, commit 1065499)

  • Reworded 'ty is pinned in the dev dependency group' -> 'in the dev dependency group and version-locked via uv.lock' (pyproject uses a lower bound; the lockfile does the exact pinning) in both the CI comment and the hook header.
  • Install instruction now notes the uv sync prerequisite: 'Install once (after uv sync): uv run pre-commit install'.

No other changes needed.

@neuromechanist neuromechanist merged commit f821104 into main Jul 14, 2026
6 checks passed
@neuromechanist neuromechanist deleted the 119-ci-enforce-ty-type-checking-+-add-pre-commit-config-ruff-+-ty branch July 14, 2026 14:31
@neuromechanist neuromechanist mentioned this pull request Jul 14, 2026
3 tasks
neuromechanist added a commit that referenced this pull request Jul 14, 2026
Release 0.1.2: NumPy do_reject outlier rejection (#123) + reject
robustness (#127), repo-wide ty type-checking enforced in CI/pre-commit
(#124, #125), and the comprehensive validation-evidence docs (#108).
Backfill the missing 0.1.1 changelog entry and add 0.1.2.
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.

CI: enforce ty type-checking + add pre-commit config (ruff + ty)

1 participant