Pre-commit Hooks Setup Guide
Overview
This project uses pre-commit to automatically run code quality checks before every commit. This ensures code consistency, catches errors early, and maintains high code quality standards.
What Are Pre-commit Hooks?
Pre-commit hooks are automated checks that run before you commit code. They:
- Prevent bad commits: Catch issues before they enter the codebase
- Enforce standards: Automatically format code and check for errors
- Save time: Find problems immediately instead of in CI/CD
- Improve quality: Maintain consistent code style across the team
Installation
First-Time Setup
# 1. Sync dependencies (includes pre-commit)
uv sync
# 2. Install the git hooks
uv run pre-commit install
# 3. (Optional) Run on all files to test
uv run pre-commit run --all-files
Verification
After installation, pre-commit will run automatically on every git commit. You'll see output like:
trailing whitespace...................................Passed
end of file fixer....................................Passed
check yaml..........................................Passed
ruff.................................................Passed
mypy.................................................Passed
Configured Hooks
Our pre-commit configuration includes:
General File Checks
- trailing-whitespace: Remove trailing spaces (except in markdown)
- end-of-file-fixer: Ensure files end with a newline
- check-yaml: Validate YAML syntax
- check-json: Validate JSON syntax
- check-toml: Validate TOML syntax
- check-added-large-files: Prevent files >1MB from being committed
- check-merge-conflict: Detect merge conflict markers
- detect-private-key: Prevent committing private keys
Python Checks
- check-ast: Validate Python syntax
- check-builtin-literals: Require literal syntax (e.g.,
[]notlist()) - debug-statements: Prevent debug statements like
breakpoint()
Linting and Formatting
- ruff: Fast Python linter (replaces flake8, isort, etc.)
- ruff-format: Python code formatter
- mypy: Static type checking
- bandit: Security vulnerability scanning
Markdown and YAML
- markdownlint: Markdown file formatting
- pretty-format-yaml: YAML formatting
Notebook Cleaning
- nbstripout: Remove notebook outputs before commit
Security
- detect-secrets: Scan for accidentally committed secrets
Usage
Automatic (Recommended)
Pre-commit runs automatically when you commit:
If a hook fails:
- Fix the reported issues
- Stage the fixes:
git add . - Commit again:
git commit -m "Your message"
Manual Run
Run hooks manually on specific files:
# Run on staged files
uv run pre-commit run
# Run on all files
uv run pre-commit run --all-files
# Run specific hook
uv run pre-commit run ruff --all-files
uv run pre-commit run mypy --all-files
Skip Hooks (Use Sparingly)
If you need to bypass hooks (not recommended):
Warning: Skipping hooks means issues will be caught in CI/CD instead.
Disable/Enable Hooks
If you need to temporarily or permanently disable pre-commit hooks:
Disable hooks (removes git hook):
After uninstalling, commits will proceed without running any hooks.
Re-enable hooks (reinstalls git hook):
Use cases for disabling:
- Working on a large refactoring where you want to commit in stages
- Running formatters/linters manually before committing
- Troubleshooting hook issues
- Temporarily bypassing slow hooks during rapid iteration
Note: Even with hooks disabled, it's best practice to run formatters and linters manually before committing:
# Run all formatters and linters manually
uv run ruff format src tests
uv run ruff check --fix src tests
uv run mypy src
uv run bandit -r src -c pyproject.toml
uv run pymarkdownlnt scan docs
Common Issues
Hook Fails on Commit
Problem: Pre-commit found issues in your code.
Solution:
- Read the error message carefully
- Fix the reported issues
- Stage the fixes:
git add . - Commit again
Mypy Type Errors
Problem: mypy reports type errors.
Solution:
# Run mypy to see full output
uv run mypy src
# Fix type annotations
# Add type hints, use type: ignore if needed
Ruff Formatting Issues
Problem: Code doesn't match ruff style.
Solution:
Large Files
Problem: Trying to commit files >1MB.
Solution:
- Add to
.gitignoreif it shouldn't be committed - Use Git LFS for large files
- Or adjust the limit in
.pre-commit-config.yaml
Slow Hook Runs
Problem: Hooks take a long time.
Solution:
- Pre-commit caches environments, first run is slower
- Run
pre-commit gcto clean up old environments - Consider disabling heavy hooks locally (edit
.pre-commit-config.yaml)
Configuration
Pre-commit is configured in .pre-commit-config.yaml. You can:
Update Hook Versions
Disable Specific Hooks
Edit .pre-commit-config.yaml and comment out unwanted hooks:
Adjust Hook Settings
Example - change file size limit:
Integration with VS Code
Pre-commit works alongside VS Code extensions:
- Pre-commit runs on git commit: Catches everything before commit
- VS Code extensions run on save: Immediate feedback while coding
- CI/CD runs on push: Final verification
This multi-layered approach ensures code quality at every step.
Best Practices
DO
✅ Run pre-commit run --all-files after updating hooks
✅ Commit frequently with small changesets
✅ Fix issues as they arise (don't accumulate)
✅ Keep .pre-commit-config.yaml in sync with pyproject.toml
✅ Update hooks regularly: pre-commit autoupdate
DON'T
❌ Skip hooks without good reason
❌ Commit large batches of changes
❌ Ignore type errors (fix or add # type: ignore)
❌ Commit debugging code
❌ Commit secrets or API keys
CI/CD Integration
Pre-commit hooks match our GitHub Actions workflows:
| Hook | CI/CD Workflow |
|---|---|
| ruff | .github/workflows/python-lint.yml |
| mypy | .github/workflows/python-typecheck.yml |
| pytest | .github/workflows/python-tests.yml |
| bandit | .github/workflows/security-audit.yml |
| markdownlint | .github/workflows/markdown-lint.yml |
Running pre-commit locally ensures CI/CD passes.
Troubleshooting
Hooks Not Running
# Reinstall hooks
uv run pre-commit uninstall
uv run pre-commit install
# Verify installation
uv run pre-commit run --all-files
Environment Issues
# Clean pre-commit cache
uv run pre-commit clean
uv run pre-commit gc
# Reinstall environments
uv run pre-commit install --install-hooks
Hook Version Conflicts
Additional Resources
Quick Reference
# Installation
uv run pre-commit install
# Run manually
uv run pre-commit run --all-files
# Update hooks
uv run pre-commit autoupdate
# Clean cache
uv run pre-commit clean
# Uninstall
uv run pre-commit uninstall
# Skip hooks (not recommended)
git commit --no-verify
Summary
Pre-commit hooks are a powerful tool for maintaining code quality. They:
- Catch issues early - Before they enter the codebase
- Save time - Automated checks instead of manual review
- Enforce standards - Consistent code style across the team
- Integrate with CI/CD - Match GitHub Actions workflows
Follow this guide to use pre-commit effectively in the AYNE project!