Skip to content

CI integration

Every serious project wires doctor into its pre-merge CI so regressions can't slip past a PR. Below is the template used on altiusone — adapt to your stack.

Prerequisites

  • requirements-dev.txt pins django-test-doctor>=0.5.0 (or whichever minimum version you need).
  • Your build image (or CI runner) can run Django.

GitHub Actions template

name: django-doctor

on:
  pull_request:
    branches: [main, develop]
    paths:
      - '**/*.py'
      - '**/*.html'
      - 'requirements*.txt'
      - '.github/workflows/django-doctor.yml'
  workflow_dispatch:

jobs:
  doctor:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgis/postgis:15-3.4
        env:
          POSTGRES_DB: myproject_test
          POSTGRES_USER: myproject
          POSTGRES_PASSWORD: testpassword
        ports:
          - 5432:5432

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install -r requirements-dev.txt
      - name: doctor
        env:
          DATABASE_URL: postgres://myproject:testpassword@localhost:5432/myproject_test
          SECRET_KEY: ci-not-for-production
          ALLOWED_HOSTS: '*'
          DEBUG: 'True'
        run: python manage.py doctor --section system,forms,forms_meta,admin,models,migrations,drf --ci

Running urls and post_smoke in CI

These two touch the database (create a superuser, POST forms). They need every app-specific env var your project reads at boot (REDIS_URL, MINIO_ENDPOINT, …). The simpler pattern is:

  1. Build your Docker image.
  2. docker run it with the right env.
  3. Exec python manage.py doctor --section urls,post_smoke --ci inside the container.

Baseline strategy for legacy projects

If ./manage.py doctor --ci explodes with hundreds of pre-existing findings, don't fail the build on day one. Two approaches:

[tool.django-doctor]
ignore = [
  "models:models.str_missing",       # 20 legacy models, ok
  "urls:urls.get.5xx",               # until the crash list is worked through
]
[tool.django-doctor]
fail_on = ["critical"]   # only crash blocks CI; ERRORs are surfaced but not blocking

Lower the bar as you clear the backlog.

Report artifact

Keep the JSON output for your own dashboards:

      - name: doctor (report)
        run: python manage.py doctor --json > doctor.json
      - uses: actions/upload-artifact@v4
        with:
          name: doctor-findings
          path: doctor.json