TypeDialog/docs/pre-commit-setup.md

350 lines
6.1 KiB
Markdown
Raw Normal View History

2025-12-24 03:11:32 +00:00
# Pre-commit Hook Setup
Automated linting and validation before every commit.
## Installation
### 1. Install pre-commit
**macOS/Linux (via pip):**
```bash
pip install pre-commit
# Or with pipx (recommended)
pipx install pre-commit
```
**macOS (via Homebrew):**
```bash
brew install pre-commit
```
**Verify installation:**
```bash
pre-commit --version
```
### 2. Install the hooks
From the project root:
```bash
pre-commit install
```
This creates `.git/hooks/pre-commit` that runs automatically on `git commit`.
## What Gets Checked
The pre-commit hook runs these checks **automatically before every commit**:
### General Checks
- **Trailing whitespace** - Removes trailing spaces (except in `.md` files)
- **End-of-file fixer** - Ensures files end with newline
- **YAML/TOML/JSON validation** - Syntax checking
- **Large files** - Prevents files >1MB
- **Merge conflicts** - Detects conflict markers
- **Line endings** - Normalizes to LF
### Language-Specific Linting
#### Rust
- **`cargo fmt`** - Code formatting check
- **`cargo clippy`** - Linting with warnings as errors
#### Shell Scripts
- **`shellcheck`** - Bash/shell script analysis
#### Markdown (docs/ only)
- **`markdownlint-cli2`** - Syntax validation (MD rules)
- **`vale`** - Prose quality (weasel words, etc.)
#### Nickel
- **`nickel typecheck`** - Type checking for `.ncl` files
#### Nushell
- **`nu --check`** - Script validation for `.nu` files
### Security
- **`cargo audit`** - Dependency vulnerability scan (manual stage only)
## Usage
### Automatic (Recommended)
Pre-commit runs automatically on `git commit`:
```bash
git add docs/README.md
git commit -m "Update README"
# Pre-commit hooks run automatically
```
### Manual Run
Run all hooks on all files:
```bash
pre-commit run --all-files
```
Run specific hook:
```bash
pre-commit run cargo-fmt --all-files
pre-commit run markdownlint-cli2 --all-files
pre-commit run vale --all-files
```
Run hooks on staged files only:
```bash
pre-commit run
```
### Skip Hooks (Emergency Only)
To bypass hooks (use sparingly):
```bash
git commit --no-verify -m "Emergency fix"
```
**Note**: CI will still run all checks, so bypassing locally doesn't skip validation.
## Hook Behavior
### Blocking vs Non-Blocking
**Blocking (commit fails if check fails):**
- cargo fmt
- cargo clippy
- markdownlint-cli2
- shellcheck
- nickel typecheck
- nushell check
**Non-Blocking (warnings logged, commit succeeds):**
- vale (prose quality warnings don't block commits)
### Vale Configuration
Vale is configured to be **informative but not blocking**:
- **0 errors** → Commit succeeds
- **Warnings** → Logged but commit proceeds
- Encourages better prose without being disruptive
To make Vale blocking, edit `.pre-commit-config.yaml`:
```yaml
# Change this:
entry: bash -c 'vale docs/ || exit 0'
# To this:
entry: bash -c 'vale docs/'
```
## Updating Hooks
Update to latest hook versions:
```bash
pre-commit autoupdate
```
This updates the `rev:` fields in `.pre-commit-config.yaml`.
## Troubleshooting
### Hook fails: "command not found"
**Problem**: Tool not installed (e.g., `cargo`, `vale`, `nickel`, `nu`)
**Solution**: Install the missing tool:
```bash
# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Vale
brew install vale # macOS
# See https://vale.sh for other platforms
# Nickel
cargo install nickel-lang-cli
# Nushell
cargo install nu
```
### Hooks are slow
**Problem**: `cargo clippy` takes 30+ seconds
**Solution**: Use `--no-verify` for quick commits, let CI handle full validation:
```bash
git commit --no-verify -m "WIP: quick fix"
# Later, when ready:
pre-commit run --all-files
```
### Markdownlint fails on valid Markdown
**Problem**: False positive from markdownlint
**Solution**: Update `.markdownlint-cli2.jsonc` to disable the rule:
```json
{
"config": {
"default": true,
"MD013": false, // Example: disable line length
"MD033": false // Example: allow HTML
}
}
```
### Vale warnings are too noisy
**Problem**: Too many prose quality warnings
**Solution**: Adjust `.vale.ini` to disable specific rules:
```ini
[*.md]
write-good.Weasel = NO # Disable weasel word warnings
```
Or set higher alert level:
```ini
MinAlertLevel = error # Only show errors, not warnings
```
## Best Practices
### 1. Run Before First Commit
After installing hooks, test them:
```bash
pre-commit run --all-files
```
Fix any issues before committing.
### 2. Keep Commits Small
Smaller commits = faster hook execution.
### 3. Stage Incrementally
Stage related changes together:
```bash
git add docs/README.md docs/build.md
git commit -m "Update build docs"
# Only checks staged files
```
### 4. Use --no-verify Sparingly
Reserve `--no-verify` for emergencies:
- Hotfixes
- Reverts
- Time-critical patches
CI will catch issues anyway.
### 5. Update Hooks Regularly
Monthly:
```bash
pre-commit autoupdate
pre-commit run --all-files
```
## Integration with CI
Pre-commit hooks mirror CI checks:
**Local (pre-commit)**:
- Fast feedback before commit
- Catches obvious issues early
- Optional (can bypass with `--no-verify`)
**CI (GitHub Actions)**:
- Comprehensive validation
- Required for PRs
- Cannot be bypassed
Both run the same checks, so passing locally = passing CI.
## Disabling Hooks Temporarily
Disable all hooks:
```bash
pre-commit uninstall
```
Re-enable:
```bash
pre-commit install
```
Disable specific hook (edit `.pre-commit-config.yaml`):
```yaml
- id: cargo-clippy
# Add this to disable:
stages: [manual]
```
Then run manually with:
```bash
pre-commit run cargo-clippy --all-files --hook-stage manual
```
## Summary
Pre-commit hooks provide:
-**Automated quality checks** before every commit
-**Fast feedback** (catch issues in seconds, not minutes)
-**Consistent standards** across all contributors
-**Optional but recommended** (can bypass if needed)
Install once, benefit forever:
```bash
pip install pre-commit
pre-commit install
```
---
**See also**:
- [.pre-commit-config.yaml](../.pre-commit-config.yaml) - Hook configuration
- [development.md](development.md) - Development workflow
- [CI configuration](../.github/workflows/ci.yml) - GitHub Actions