Setup Linting

This guide explains how to set up documentation linting in your repository to catch issues before commit and during CI/CD.

Overview

DocBuilder’s linting system validates documentation files against Hugo and DocBuilder best practices, catching common issues like:

  • Invalid filenames (spaces, uppercase, special characters)
  • Malformed frontmatter
  • Broken internal links
  • Invalid double extensions (except whitelisted .drawio.png, .drawio.svg)

Linting can run:

  • Manually: docbuilder lint command
  • Pre-commit: Git hooks (lefthook or traditional)
  • CI/CD: GitHub Actions, GitLab CI, etc.

Prerequisites

  • DocBuilder installed (go install or download binary)
  • Git repository with documentation (usually in docs/ or documentation/)

Manual Linting

Basic Usage

Run linting from your repository root:

1
2
3
4
5
6
7
8
# Auto-detects docs/ or documentation/ directory
docbuilder lint

# Lint specific directory
docbuilder lint ./docs

# Lint current directory explicitly
docbuilder lint .

Understanding Output

Linting documentation in: ./docs
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✗ docs/API Guide.md
  ERROR: Invalid filename
  └─ Contains uppercase letters and spaces
  
  Current:  docs/API Guide.md
  Suggested: docs/api-guide.md

✓ docs/getting-started.md
✓ docs/images/architecture.drawio.png (whitelisted)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Results:
  3 files scanned
  1 error (blocks build)
  0 warnings

Exit Codes

  • 0: No issues (clean)
  • 1: Warnings present (should fix)
  • 2: Errors found (blocks build)
  • 3: Execution error (filesystem access, etc.)

Auto-Fix

Automatically fix common issues:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Dry-run mode (preview changes)
docbuilder lint --fix --dry-run

# Interactive mode (prompts for confirmation)
docbuilder lint --fix

# Non-interactive mode (CI/automation)
docbuilder lint --fix --yes

# Force overwrite existing files
docbuilder lint --fix --force

Auto-fix will:

  • Rename files to lowercase with hyphens
  • Update all internal links to renamed files
  • Regenerate frontmatter fingerprint values, setting lastmod (UTC YYYY-MM-DD) when a fingerprint changes
  • Preserve Git history with git mv
  • Show detailed report of changes

Output Formats

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Human-readable (default)
docbuilder lint

# JSON for CI/CD integration
docbuilder lint --format=json > lint-report.json

# Quiet mode (errors only)
docbuilder lint --quiet

# Verbose mode (detailed output)
docbuilder lint --verbose

Git Hooks Integration

Lefthook is a fast, modern Git hooks manager with better performance and easier configuration.

Installation

macOS:

1
brew install lefthook

Linux:

1
2
3
4
5
6
# Using Go
go install github.com/evilmartians/lefthook@latest

# Or download binary from releases
curl -1sLf 'https://dl.cloudsmith.io/public/evilmartians/lefthook/setup.deb.sh' | sudo -E bash
sudo apt install lefthook

Windows:

1
scoop install lefthook

Configuration

Create lefthook.yml in your repository root:

1
2
3
4
5
6
7
8
# lefthook.yml
pre-commit:
  parallel: true
  commands:
    lint-docs:
      glob: "*.{md,markdown,png,jpg,jpeg,gif,svg}"
      run: docbuilder lint {staged_files} --quiet
      stage_fixed: true  # Auto-stage files fixed with --fix

Setup in Repository

1
2
3
4
5
# Install hooks (one-time per clone)
lefthook install

# Verify installation
lefthook run pre-commit --verbose

With Auto-Fix

To automatically fix issues on commit:

1
2
3
4
5
6
7
8
# lefthook.yml
pre-commit:
  parallel: true
  commands:
    lint-docs:
      glob: "*.{md,markdown,png,jpg,jpeg,gif,svg}"
      run: docbuilder lint {staged_files} --fix --yes --quiet
      stage_fixed: true

Workflow

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Make changes to documentation
vim docs/API Guide.md

# Commit triggers automatic linting
git add docs/
git commit -m "Add API documentation"

# Lefthook runs automatically
Lefthook > pre-commit > lint-docs:
✓ All staged files pass linting

[main a1b2c3d] Add API documentation

Option 2: Traditional Pre-Commit Hook

For repositories that prefer traditional Git hooks without additional tools.

Installation

1
2
3
4
5
6
# Automated installation
docbuilder lint install-hook

# Manual installation
curl -o .git/hooks/pre-commit https://raw.githubusercontent.com/your-org/docbuilder/main/scripts/pre-commit-hook.sh
chmod +x .git/hooks/pre-commit

Manual Hook Setup

Create .git/hooks/pre-commit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/sh
# DocBuilder documentation linting pre-commit hook

# Only lint staged markdown and asset files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(md|markdown|png|jpg|jpeg|gif|svg)$')

if [ -n "$STAGED_FILES" ]; then
  echo "Linting staged documentation files..."
  docbuilder lint $STAGED_FILES --quiet
  
  LINT_EXIT=$?
  
  if [ $LINT_EXIT -eq 2 ]; then
    echo ""
    echo "❌ Lint errors found. Commit blocked."
    echo "Fix errors or run: docbuilder lint --fix"
    exit 1
  elif [ $LINT_EXIT -eq 1 ]; then
    echo ""
    echo "⚠️  Lint warnings present. Consider fixing before commit."
    echo "To auto-fix: docbuilder lint --fix"
    # Allow commit but show warning
    exit 0
  fi
fi

exit 0

Make executable:

1
chmod +x .git/hooks/pre-commit

Comparison: Lefthook vs Traditional Hooks

Feature Lefthook Traditional Hook
Installation Single command: lefthook install Manual script creation
Configuration Checked into repo (lefthook.yml) Not in repo (.git/hooks/)
Performance Parallel execution Sequential
Portability Works across team (committed config) Each clone needs manual setup
Auto-staging Built-in (stage_fixed: true) Manual implementation
Maintenance Easy to update (edit lefthook.yml) Edit script in each clone
Dependencies Requires lefthook binary Only Git

Recommendation: Use lefthook for better developer experience and maintainability.

Skipping Hooks (When Needed)

Sometimes you need to commit without running hooks:

1
2
3
4
5
# Skip all hooks
git commit --no-verify -m "Emergency hotfix"

# With lefthook, skip specific commands
LEFTHOOK_EXCLUDE=lint-docs git commit -m "Skip linting"

⚠️ Warning: Skipping linting may cause CI failures. Use sparingly.

Team Adoption

Gradual Rollout

Week 1: Introduce linting

1
2
3
4
# Team members run manually
docbuilder lint
docbuilder lint --fix --dry-run  # Show what would change
docbuilder lint --fix            # Apply fixes

Week 2: Add lefthook configuration

1
2
3
4
5
# Start with warnings only (non-blocking)
pre-commit:
  commands:
    lint-docs:
      run: docbuilder lint {staged_files} --quiet || true  # Don't block commits

Week 3: Enable enforcement

1
2
3
4
5
# Remove || true to block commits with errors
pre-commit:
  commands:
    lint-docs:
      run: docbuilder lint {staged_files} --quiet

Team Setup Guide

Share this with your team:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
## Documentation Linting Setup (One-Time)

1. Install lefthook:
   - macOS: `brew install lefthook`
   - Linux: `go install github.com/evilmartians/lefthook@latest`
   - Windows: `scoop install lefthook`

2. Install hooks in your clone:
   ```bash
   cd your-repo
   lefthook install
  1. Verify it works:

    1
    
    lefthook run pre-commit --verbose
  2. Clean up existing docs (one-time):

    1
    2
    3
    4
    
    docbuilder lint --fix --dry-run  # Preview changes
    docbuilder lint --fix            # Apply fixes
    git add -A
    git commit -m "docs: normalize filenames for linting"

That’s it! Linting now runs automatically on every commit.

## Troubleshooting

### Issue: "docbuilder: command not found"

**Solution**: Add DocBuilder to PATH:

```bash
# Add to ~/.bashrc or ~/.zshrc
export PATH="$PATH:$(go env GOPATH)/bin"

# Or install globally
sudo cp $(which docbuilder) /usr/local/bin/

Issue: Hook doesn’t run on commit

Lefthook:

1
2
3
4
5
# Reinstall hooks
lefthook install

# Check status
lefthook run pre-commit --verbose

Traditional hook:

1
2
3
# Verify hook exists and is executable
ls -la .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

Issue: Too many warnings/errors in existing repo

Solution: Bulk fix existing issues:

1
2
3
4
5
6
7
8
9
# Preview all fixes
docbuilder lint --fix --dry-run

# Review changes and apply
docbuilder lint --fix

# Commit cleanup
git add -A
git commit -m "docs: normalize filenames and fix linting issues"

Issue: Lefthook slows down commits

Solution: Optimize configuration:

1
2
3
4
5
6
7
8
9
pre-commit:
  parallel: true  # Run commands in parallel
  commands:
    lint-docs:
      glob: "*.{md,markdown}"  # Only markdown files
      run: docbuilder lint {staged_files} --quiet
      skip:
        - merge      # Skip during merge commits
        - rebase     # Skip during rebase

Issue: Need to commit despite linting errors

1
2
3
4
5
# Emergency bypass (use sparingly)
git commit --no-verify -m "Hotfix: critical issue"

# Or with lefthook
LEFTHOOK=0 git commit -m "Skip all hooks"

Next Steps

Additional Resources

permalink[setup-linting](https://docs.home.luguber.info/_uid/fb886a4a-1a7f-4d2d-9789-791247e160a0/)