Skip to main content

Unified health scoring for Odoo custom addons

Project description

Odoo Doctor 🩺

Unified health scoring for Odoo custom addons.

Combines confidence-aware static analysis with optional external linters (Ruff, Pylint-Odoo) to produce a single 0–100 score per addon — designed for CI pipelines and AI coding agents.

Python 3.10+ License: MIT


Quick Start

# 1. Chạy ngay (không cần install)
pipx run odoo-doctor scan .

# 2. Install global
pip install odoo-doctor
odoo-doctor scan .

# 3. JSON output cho CI / agents
odoo-doctor scan . --json

# 4. Fail nếu score < 80
odoo-doctor scan . --min-score 80

# 5. Chỉ scan file đã thay đổi (PR review)
odoo-doctor scan . --diff main --json

What it checks

Rule Tier Category
raw-sql-string-interpolation P0 Security
missing-access-csv P0 Security
unknown-model-in-access-csv P1 Correctness
duplicate-xml-id P1 Correctness
view-field-not-in-model P1 Correctness
button-method-not-found P1 Correctness
missing-xml-ref P1 Correctness
manifest-missing-dependency P1 Module Hygiene
manifest-missing-required-fields P2 Module Hygiene
search-in-loop P1 Performance
public-controller-sudo-risk P1 Security
unbounded-search P2 Performance
manifest-data-order-risk P2 Module Hygiene
override-missing-super P1 Correctness
compute-missing-depends P2 Correctness

Plus Ruff and Pylint-Odoo findings when those tools are installed.


Score explained

Each category score starts at 100 and loses points per high-confidence finding, where each finding deducts tier_impact × category_weight (default weight 1.0; override via [category_weights]). The overall score blends only in-scope categories (those with at least one active rule):

category_score = max(0, 100 − Σ(tier_impact × category_weight))
overall        = 0.4 × min(in_scope_category_scores)
               + 0.6 × avg(in_scope_category_scores)

Tier impacts: P0 = 25, P1 = 10, P2 = 4, P3 = 1.

Label Range
Excellent 90–100
Good 75–89
Needs work 50–74
Critical 0–49

Each finding deducts points by tier: P0 = −25, P1 = −10, P2 = −4, P3 = −1.
Only high confidence findings count toward the score.


Configuration

odoo-doctor init   # creates odoo-doctor.toml
[odoo-doctor]
odoo_version = "17.0"
addons_paths = ["."]
odoo_source_path = "/path/to/odoo/source"
capabilities = ["enterprise", "owl"]
min_score = 75

[adapters]
ruff = true
pylint_odoo = false

[severity]
"search-in-loop" = "warning"

[ignore]
rules = []
files = ["**/migrations/**"]
modules = []

[category_weights]
Security = 1.5

[surfaces.pr_comment]
min_confidence = "all"
categories = []

[surfaces.ci_failure]
min_confidence = "high"
categories = []

CI Integration

GitHub Actions

The easiest way to integrate Odoo Doctor into GitHub Actions is using our official composite action. See .github/workflows/odoo-doctor.example.yml for a full example.

- name: Odoo Doctor Scan
  uses: minhhq-a1/odoo-doctor@v0.3.0
  with:
    fail-on: warning
    min-score: 75
    diff-base: main
    pr-comment: true
    paths: "."

If you prefer pip install, you can run it directly:

- name: Odoo Doctor (pip)
  run: |
    pip install odoo-doctor
    odoo-doctor scan . --format github --min-score 75 --fail-on error

SARIF & Baseline Mode

For GitHub Code Scanning and IDE integration:

odoo-doctor scan . --format sarif > results.sarif
# Then upload via github/codeql-action/upload-sarif

To capture current debt and block only new findings in CI:

odoo-doctor scan . --write-baseline .odoo-doctor-baseline.json
# Commit the baseline, then in CI:
odoo-doctor scan . --baseline .odoo-doctor-baseline.json --fail-on warning

CI/PR Surfaces

  • --format github: Emits GitHub Actions annotations inline.
  • --score-delta <base-ref>: Opt-in PR score delta. It does a worktree-isolated second scan and needs git history (fetch-depth: 0 in Actions).
  • Sticky PR comment: Posted/updated via gh when --format github runs in a PR with a valid GH_TOKEN. Idempotent via a hidden marker.

pre-commit

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: odoo-doctor
        name: Odoo Doctor
        language: system
        entry: odoo-doctor scan --diff HEAD --fail-on error
        pass_filenames: false
        types: [python]

Agent Usage

Odoo Doctor is designed for AI coding agents. Install the SKILL.md files:

odoo-doctor install   # installs to .odoo-doctor/skills/

Then in your agent workflow:

# After editing Odoo code
odoo-doctor scan . --diff main --json

# Fix P0/P1 findings with confidence: "high"
# Re-scan to verify fixes
odoo-doctor scan . --diff main --json

Use odoo-doctor rules explain <rule-name> to understand any finding.


Generating stubs for your Odoo version

Bundled stubs cover 17.0, 18.0, 19.0 (core models only).
For full accuracy, generate from source or a live instance:

# From Odoo source checkout
python -m odoo_doctor.graph.stubs.build_stubs source \
  --odoo-path /path/to/odoo \
  --version 17.0

# From a live Odoo instance (no source needed)
python -m odoo_doctor.graph.stubs.build_stubs rpc \
  --rpc-url http://localhost:8069 \
  --rpc-db mydb \
  --rpc-password admin \
  --version 17.0

The generated JSON is written to src/odoo_doctor/graph/stubs/data/<version>.json
(or --output <path> for a custom location).


Inline suppression

x = self.env.cr.execute(f"SELECT ...")  # odoo-doctor: disable=raw-sql-string-interpolation
<record id="my_record" model="ir.ui.view">  <!-- odoo-doctor: disable=duplicate-xml-id -->

Exit codes

Code Meaning
0 Clean — no triggered thresholds
1 Findings at or above --fail-on severity
2 One or more modules score below --min-score
3 Invalid argument, out-of-range --min-score, or git/ref failure

Development

git clone https://github.com/minhhq-a1/odoo-doctor
cd odoo-doctor
pip install -e ".[dev]"
pytest                    # 324+ test cases
pytest --cov=odoo_doctor  # with coverage

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

odoo_doctor-0.3.0.tar.gz (65.5 kB view details)

Uploaded Source

Built Distribution

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

odoo_doctor-0.3.0-py3-none-any.whl (102.6 kB view details)

Uploaded Python 3

File details

Details for the file odoo_doctor-0.3.0.tar.gz.

File metadata

  • Download URL: odoo_doctor-0.3.0.tar.gz
  • Upload date:
  • Size: 65.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for odoo_doctor-0.3.0.tar.gz
Algorithm Hash digest
SHA256 08277d38a2e6f2057f6d08438bb63ddb4d065b94ef746939e1bd9f237638c6d6
MD5 6d675d6a6c24c57e77b2666461b23bbf
BLAKE2b-256 75b3564331adfa3d02a5c3e00858f4b5295e52fc02fcb08b1f576705c024907a

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_doctor-0.3.0.tar.gz:

Publisher: publish.yml on minhhq-a1/odoo-doctor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file odoo_doctor-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: odoo_doctor-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 102.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for odoo_doctor-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f22697d4b0b0b509aeeac7831e625a3d6854d3be7df9ae8d6880ae70396357cf
MD5 21cd917ca54fbe3cb8081db80a5857c6
BLAKE2b-256 6927e4aaae4de879ee227b6d1ef77309c6c76dfdaa3aa389a04f0d39233b730b

See more details on using hashes here.

Provenance

The following attestation bundles were made for odoo_doctor-0.3.0-py3-none-any.whl:

Publisher: publish.yml on minhhq-a1/odoo-doctor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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