Skip to content

[Feature]: Replace pre-commit with lefthook + pixi tasks #854

@chrisburr

Description

@chrisburr

User Story

As a developer,
I want linting and formatting tools managed in a single place (pixi.lock),
So that I don't have duplicate version tracking and I benefit from Renovate's cooldown for supply-chain protection.

Feature Description

Replace pre-commit (and pre-commit.ci autoupdates) with lefthook, running checks via pixi tasks.

Motivation:

  • Duplicate dependency management: Tool versions (ruff, mypy, codespell, etc.) are tracked in both .pre-commit-config.yaml and the pixi environment. With lefthook, versions are pinned once in pixi.lock.
  • Supply-chain risk: pre-commit.ci autoupdates have no cooldown — new hook versions are proposed immediately on release. Moving to pixi-managed dependencies means updates go through Renovate with our existing 7-day minimumReleaseAge.
  • Stability: pre-commit doesn't use lockfiles — it pins the hook repo rev but not transitive dependencies. A hook's dependencies can change or break between runs without any version change in .pre-commit-config.yaml. pixi.lock pins the full dependency tree.
  • Simpler CI: CI already uses pixi. Instead of installing pre-commit separately, CI would just run pixi run lint / pixi run typecheck.
  • Performance: lefthook runs hooks in parallel by default and doesn't maintain its own virtualenvs.

Definition of Done

  • lefthook added as a pixi dependency (conda-forge::lefthook)
  • Pixi tasks added for each check (e.g. ruff-check, ruff-format, mypy, codespell, mdformat)
  • lefthook.yml created using the jobs API to run formatters first, then linters in parallel
  • .pre-commit-config.yaml and pre-commit.ci integration removed
  • CI workflows updated to use pixi tasks directly
  • conventional-pre-commit moved to a pip dependency in pixi.toml
  • Local hooks (lollygag check, pixi docs generation, settings doc check) ported as pixi tasks

Alternatives Considered

  • Renovate's pre-commit manager: Disabled by default indefinitely due to disagreements with the pre-commit project. Would add cooldowns to pre-commit.ci updates but doesn't solve the duplicate dependency management or lockfile issues.
  • Keeping pre-commit with ci: autoupdate_schedule: never: Removes the cooldown gap but still leaves duplicate version tracking and no lockfile for transitive dependencies.

Additional Context

  • lefthook's jobs API (v1.10.0+) allows sequential groups with internal parallelism, so formatters run before linters without conflicts
  • conventional-pre-commit is a pure Python package that can be pip-installed within the pixi environment and called directly from lefthook's commit-msg hook

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions