Thanks for your interest in contributing to docvet! This guide covers everything you need to get started. Browse the documentation site for detailed references, or see the Development Guide for full coding conventions.
Use the issue templates on the Issues page:
- Bug Report -- reproduce steps, environment info, and logs
- Feature Request -- problem statement, proposed solution, acceptance criteria
- Enhancement -- improvements to existing functionality
- Python >= 3.12
- uv -- install guide
- git
- pre-commit -- install guide
# 1. Fork the repo on GitHub (click "Fork" button)
# 2. Clone your fork
git clone https://github.com/<your-username>/docvet.git
cd docvet
# 3. Add the upstream remote
git remote add upstream https://github.com/Alberto-Codes/docvet.git
# 4. Create a feature branch
git checkout -b feat/<scope>-<description># Install in development mode with all dev dependencies
uv sync --dev
# With optional griffe support
uv sync --dev --extra griffe
# Verify installation
uv run docvet --helpdocvet uses pre-commit hooks to catch issues before they reach CI. Pre-commit is not a project dependency -- if you don't have it yet, see the install guide. Then activate the hooks:
pre-commit installSeven hooks run automatically on each commit:
| Hook | What it checks |
|---|---|
| yamllint | YAML syntax and formatting |
| actionlint | GitHub Actions workflow validity |
| ruff-check | Python linting |
| ruff-format | Python code formatting |
| ty | Type checking |
| pytest | Full test suite |
| docvet | Docstring quality on staged files |
All hooks must pass before the commit succeeds. The docvet hook runs docvet check --staged with all four checks enforced, so docvet dogfoods itself on every commit.
All five gates must pass before opening a PR. Run them locally:
uv run ruff check . # Linting
uv run ruff format --check . # Format check
uv run ty check # Type checking
uv run pytest # Tests (CI enforces 85% coverage)
uv run docvet check --all # Docstring quality (all 4 checks)To auto-fix linting and formatting issues:
uv run ruff check --fix .
uv run ruff format .from __future__ import annotationsat the top of every file- Google-style docstrings on all public functions and classes
- Type hints on all function signatures (
list[str], notList[str]) - 88-char soft limit (formatter), 100-char hard limit (linter)
See the Development Guide for the full style reference.
uv run pytest # All tests
uv run pytest tests/unit # Unit tests only
uv run pytest tests/integration # Integration tests only
uv run pytest -k test_name # Single test by nameTest naming convention: test_<what>_<condition>_<expected_result>
See the Development Guide for test organization, fixtures, markers, and writing guidelines.
Commits follow the Conventional Commits format:
type(scope): description
| Type | Purpose |
|---|---|
| feat | New feature |
| fix | Bug fix |
| docs | Documentation only |
| refactor | Code restructuring |
| test | Adding or updating tests |
| chore | Maintenance tasks |
| perf | Performance improvements |
Scopes: enrichment, freshness, coverage, griffe, cli, config, discovery, ast, docs
Examples:
feat(enrichment): add missing-raises detection
fix(cli): handle empty file list gracefully
docs(enrichment): add missing-raises reference page
Do not add Co-Authored-By trailers to commits.
- Push your branch to your fork:
git push -u origin feat/<scope>-<description> - Open a draft PR against
upstream/main(non-draft PRs trigger automated review prematurely) - Fill out the PR template -- remove HTML comments, keep visible content
- PR title must follow conventional commits format:
type(scope): description - All CI checks must pass before review
- PRs are squash-merged to keep a linear history
GitHub Actions runs these checks on every PR:
| Job | What it checks |
|---|---|
| lint | ruff check + ruff format --check |
| type-check | ty check |
| test | pytest on Python 3.12 + 3.13 (85% coverage) |
| docvet | docvet check --all (all 4 checks) |
| CodeQL | Static security analysis |
CI runs uv-secure to scan for known vulnerabilities in the lockfile. If it flags something:
- Fix exists? Upgrade the package:
uv lock --upgrade-package <pkg>. No suppression needed. - No fix? Add the specific GHSA/CVE ID to the ignore list in
pyproject.toml:
[tool.uv-secure.vulnerability_criteria]
ignore_vulnerabilities = [
"GHSA-xxxx-xxxx-xxxx", # pkg X.Y.Z — description. No fix available.
]
allow_unused_ignores = falseThe allow_unused_ignores = false setting ensures CI fails once the suppression becomes stale (e.g., after Renovate bumps the package to a patched version), forcing cleanup.
See .claude/rules/dependency-vulnerabilities.md for the full triage process.
- Never add runtime dependencies beyond
typerwithout maintainer approval - Never use relative imports (full package paths only)
- Never use
__main__.py(entry point is[project.scripts]) - Never mock AST nodes in tests (use source strings with
ast.parse()) - Never put integration fixtures in the root
conftest.py - Always target
mainfor PRs (single-branch workflow)