Skip to main content

Static analysis and health scoring for dbt projects — lineage, test coverage, duplicate logic, and documentation checks.

Project description

dbt-vitals

Static analysis and health scoring for dbt projects — the "cargo clippy for dbt."

Unlike a SQL linter (indentation, keyword casing), dbt-vitals looks at your project's structure: dead models, missing tests, duplicated business logic, documentation coverage, and (given warehouse stats) incremental-model candidates. It parses manifest.json / catalog.json — the artifacts dbt already generates — so it needs no warehouse credentials of its own.

Overall Health
76/100
Warnings: 8   Critical: 0   Info: 4

What it checks

Module What it flags Needs catalog.json?
Lineage Dead/unused models, circular dependencies No
Testing Models missing unique/not_null on their likely primary key No
Duplicate Logic Repeated CASE WHEN blocks across models (candidates for a macro) No
Documentation Model/column description coverage % No
Incremental Candidates Large table-materialized models that could be incremental Yes

Local setup

Requires Python 3.9+.

git clone https://github.com/YOUR_GITHUB_USERNAME/dbt-vitals.git
cd dbt-vitals

python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate

pip install -e ".[dev]"

Run the test suite against the bundled synthetic example project:

pytest

Try the CLI against the bundled example (no real dbt project needed):

dbt-vitals analyze . --manifest examples/sample_manifest.json --catalog examples/sample_catalog.json

Run it against a real dbt project:

cd /path/to/your/dbt/project
dbt compile               # or `dbt docs generate` to also get catalog.json
dbt-vitals analyze .

CLI options

dbt-vitals analyze <target_dir>          # target_dir defaults to "."
  --manifest PATH        # override manifest.json location
  --catalog PATH         # override catalog.json location
  --json                 # machine-readable output
  --ci-comment           # markdown summary for a PR comment
  --fail-under N         # exit 1 if health score < N (CI gating)

CI integration

.github/workflows/dbt-vitals.yml is included — it runs dbt-vitals on every PR, posts the health score as a comment, and fails the build if the score drops below a threshold. Adjust the dbt compile step for your adapter/profile.

Publishing to PyPI

This is a Python package, so it's published to PyPI, not npm — pip install dbt-vitals is the equivalent of npm install.

  1. Create accounts at pypi.org and test.pypi.org (the sandbox — publish here first to make sure everything works).

  2. Generate an API token: PyPI account settings → API tokens → scope it to this project (after the first upload) or "entire account" (for the first upload, since the project doesn't exist yet).

  3. Update pyproject.toml: bump version, fix the Homepage/Issues URLs to your actual GitHub repo, add a real authors email if you want one.

  4. Build and check the package:

    pip install build twine
    python -m build                # creates dist/*.whl and dist/*.tar.gz
    twine check dist/*
    
  5. Upload to TestPyPI first:

    twine upload --repository testpypi dist/*
    # username: __token__
    # password: <your TestPyPI API token, including the pypi- prefix>
    

    Verify it installs cleanly:

    pip install --index-url https://test.pypi.org/simple/ --no-deps dbt-vitals
    dbt-vitals --version
    
  6. Once that works, upload for real:

    twine upload dist/*
    # username: __token__
    # password: <your PyPI API token>
    
  7. From then on, anyone can install it with:

    pip install dbt-vitals
    

To ship a new version later: bump version in pyproject.toml, delete the old dist/ folder, rebuild (python -m build), and twine upload dist/* again — PyPI rejects re-uploading an existing version number.

Pushing to GitHub

cd dbt-vitals
git init
git add .
git commit -m "Initial commit: dbt-vitals MVP"

# Create the repo on GitHub first (via github.com or `gh repo create`),
# then:
git remote add origin https://github.com/YOUR_GITHUB_USERNAME/dbt-vitals.git
git branch -M main
git push -u origin main

If you use the GitHub CLI instead of the website:

gh repo create dbt-vitals --public --source=. --remote=origin --push

Project layout

dbt-vitals/
  dbt_doctor/
    cli.py              # click CLI entry point
    parser.py           # manifest.json / catalog.json loading
    graph.py            # dependency graph (networkx)
    scoring.py           # health score calculation
    report.py           # terminal + CI markdown rendering
    findings.py          # shared Finding data structure
    modules/
      lineage.py         # dead models, circular deps
      testing.py         # missing test coverage
      duplicates.py       # repeated CASE-WHEN logic (via sqlglot AST)
      documentation.py    # doc coverage
      incremental.py       # incremental-model candidates
  examples/               # synthetic manifest/catalog for demos & tests
  tests/                  # pytest suite
  .github/workflows/       # CI action

Known limitations (by design, for v0.1)

  • Duplicate detection only looks at CASE WHEN expressions, not arbitrary repeated subqueries or joins.
  • Incremental candidates use a fixed row-count threshold, not a real cost/runtime estimate — that would require warehouse-specific query plans.
  • Primary key inference for the testing module is a naming heuristic (id, <model>_id, or any *_id column) since dbt's manifest has no first-class primary key concept.
  • No plugin system yet (warehouse-specific checks) — deliberately deferred, see the original scoping notes for why.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dbt_vitals-0.1.0.tar.gz (18.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dbt_vitals-0.1.0-py3-none-any.whl (18.7 kB view details)

Uploaded Python 3

File details

Details for the file dbt_vitals-0.1.0.tar.gz.

File metadata

  • Download URL: dbt_vitals-0.1.0.tar.gz
  • Upload date:
  • Size: 18.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for dbt_vitals-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2790a00b22f29b642a7c795f40c3331ddc12623b44fd9aecd459d4f0491a9d29
MD5 ba764b127a7ffb2e3bb62b3e8161d3fa
BLAKE2b-256 c2196fc2a6398485f5cf6e13f2b69ffe54ab3828766d87911d0293ac69400b05

See more details on using hashes here.

File details

Details for the file dbt_vitals-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dbt_vitals-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for dbt_vitals-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 de26e0a853cfb8e043b19cd5d43e43b56c527a48f3fbd6324012dd7299a58e68
MD5 738af48fa3f04973acb30b034a4c06f3
BLAKE2b-256 7e2c34317c0bed00281dc9486216c88f7c7d0efeed5510320d7acc74795833bf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page