[FEAT]: Add pre-commit to run tox lint/format #54

Closed
opened 2026-04-16 01:03:27 +00:00 by imAsparky · 0 comments
Owner

Before you submit

  • I have searched existing issues and this has not already been requested

Problem Statement

Add pre-commit to run tox lint/format

Proposed Solution

Add pre-commit to run tox lint/format

Alternatives Considered

No response

Additional Context

How-To: Set Up Pre-commit with Tox

This guide covers integrating pre-commit with your existing tox configuration to automatically format, lint, and test code before commits and pushes.


Prerequisites

  • tox installed and configured with lint, format, and test environments
  • A pyproject.toml or tox.ini with ruff and mypy configured under tox -e lint and tox -e format
  • Git repository initialised

Philosophy

Rather than duplicating tool configuration in both tox and pre-commit, this setup uses pre-commit purely as a trigger for existing tox environments. This means:

  • Single source of truth — all tool configuration stays in tox.ini and pyproject.toml
  • No pre-commit hook version maintenance — no pinning ruff or mypy versions in .pre-commit-config.yaml
  • Consistent behaviour — running tox -e lint manually gives identical results to the pre-commit hook

The test suite is intentionally kept out of pre-commit and CI lint checks, and instead runs on pre-push. This avoids slow commits while still catching failures before code reaches the remote.

Stage What runs When
pre-commit format + lint every git commit
pre-push test suite (py313) every git push
CI lint + type check on PR / merge

1. Install pre-commit

pip install pre-commit

2. Create .pre-commit-config.yaml

In your project root:

repos:
  - repo: local
    hooks:
      - id: tox-format
        name: Auto-fix formatting
        entry: tox -e format
        language: system
        pass_filenames: false
        stages: [pre-commit]

      - id: tox-lint
        name: Lint and type check
        entry: tox -e lint
        language: system
        pass_filenames: false
        stages: [pre-commit]

      - id: tox-test
        name: Run tests
        entry: tox -e py313
        language: system
        pass_filenames: false
        stages: [pre-push]

Hook order matters. tox-format runs before tox-lint so ruff auto-fixes issues first, then lint checks the result. If mypy fails after formatting, the commit is blocked until you fix it manually.

pass_filenames: false is required. Without it, pre-commit passes changed filenames as arguments to tox, which breaks the command.


3. Install the git hooks

pre-commit install           # installs pre-commit hook
pre-commit install --hook-type pre-push   # installs pre-push hook

Both hooks must be installed separately. Running only pre-commit install will not install the pre-push hook.


4. How it works

On every git commit:

  1. tox -e format runs first — auto-fixes ruff formatting and import order in place
  2. tox -e lint runs next — checks ruff and mypy
  3. If either fails, the commit is blocked

On every git push:

  1. tox -e py313 runs the full test suite against Python 3.13
  2. If tests fail, the push is blocked

Bypassing hooks

You can skip hooks when needed, for example on WIP branches or draft PRs:

# Skip pre-commit hooks
git commit --no-verify -m "wip: work in progress"

# Skip pre-push hooks
git push --no-verify

Use this sparingly — the hooks exist to catch issues before they reach CI or other contributors.


Running hooks manually

To run all pre-commit hooks against all files without making a commit:

pre-commit run --all-files

To run a specific hook:

pre-commit run tox-lint --all-files
pre-commit run tox-format --all-files

Uninstalling hooks

pre-commit uninstall
pre-commit uninstall --hook-type pre-push

This removes the git hooks but leaves .pre-commit-config.yaml in place.

### Before you submit - [x] I have searched existing issues and this has not already been requested ### Problem Statement Add pre-commit to run tox lint/format ### Proposed Solution Add pre-commit to run tox lint/format ### Alternatives Considered _No response_ ### Additional Context # How-To: Set Up Pre-commit with Tox This guide covers integrating pre-commit with your existing tox configuration to automatically format, lint, and test code before commits and pushes. --- ## Prerequisites - tox installed and configured with `lint`, `format`, and test environments - A `pyproject.toml` or `tox.ini` with ruff and mypy configured under `tox -e lint` and `tox -e format` - Git repository initialised --- ## Philosophy Rather than duplicating tool configuration in both tox and pre-commit, this setup uses pre-commit purely as a trigger for existing tox environments. This means: - **Single source of truth** — all tool configuration stays in `tox.ini` and `pyproject.toml` - **No pre-commit hook version maintenance** — no pinning ruff or mypy versions in `.pre-commit-config.yaml` - **Consistent behaviour** — running `tox -e lint` manually gives identical results to the pre-commit hook The test suite is intentionally kept out of pre-commit and CI lint checks, and instead runs on `pre-push`. This avoids slow commits while still catching failures before code reaches the remote. | Stage | What runs | When | |---|---|---| | `pre-commit` | format + lint | every `git commit` | | `pre-push` | test suite (py313) | every `git push` | | CI | lint + type check | on PR / merge | --- ## 1. Install pre-commit ```bash pip install pre-commit ``` --- ## 2. Create `.pre-commit-config.yaml` In your project root: ```yaml repos: - repo: local hooks: - id: tox-format name: Auto-fix formatting entry: tox -e format language: system pass_filenames: false stages: [pre-commit] - id: tox-lint name: Lint and type check entry: tox -e lint language: system pass_filenames: false stages: [pre-commit] - id: tox-test name: Run tests entry: tox -e py313 language: system pass_filenames: false stages: [pre-push] ``` > **Hook order matters.** `tox-format` runs before `tox-lint` so ruff auto-fixes issues first, then lint checks the result. If mypy fails after formatting, the commit is blocked until you fix it manually. > **`pass_filenames: false` is required.** Without it, pre-commit passes changed filenames as arguments to tox, which breaks the command. --- ## 3. Install the git hooks ```bash pre-commit install # installs pre-commit hook pre-commit install --hook-type pre-push # installs pre-push hook ``` Both hooks must be installed separately. Running only `pre-commit install` will not install the pre-push hook. --- ## 4. How it works **On every `git commit`:** 1. `tox -e format` runs first — auto-fixes ruff formatting and import order in place 2. `tox -e lint` runs next — checks ruff and mypy 3. If either fails, the commit is blocked **On every `git push`:** 1. `tox -e py313` runs the full test suite against Python 3.13 2. If tests fail, the push is blocked --- ## Bypassing hooks You can skip hooks when needed, for example on WIP branches or draft PRs: ```bash # Skip pre-commit hooks git commit --no-verify -m "wip: work in progress" # Skip pre-push hooks git push --no-verify ``` Use this sparingly — the hooks exist to catch issues before they reach CI or other contributors. --- ## Running hooks manually To run all pre-commit hooks against all files without making a commit: ```bash pre-commit run --all-files ``` To run a specific hook: ```bash pre-commit run tox-lint --all-files pre-commit run tox-format --all-files ``` --- ## Uninstalling hooks ```bash pre-commit uninstall pre-commit uninstall --hook-type pre-push ``` This removes the git hooks but leaves `.pre-commit-config.yaml` in place.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dunwright/git-herald#54
No description provided.