Skip to content

Migrating to dbt-bouncer v3.0.0#

dbt-bouncer v3.0.0 is a major release with significant internal improvements. This guide covers what changed and what you need to do to upgrade.

Who needs to do what#

You are... Action required
Using dbt-bouncer.yml config only Minimal — review config changes
Writing custom checks (subclassing BaseCheck) Must migrate — see custom check migration
Importing dbt-bouncer as a Python library Review — see API changes
Using dbt-bouncer GitHub Action No changes required (action updated internally)

Configuration changes#

Your config files still work#

Existing dbt-bouncer.yml and pyproject.toml [tool.dbt-bouncer] configurations are fully compatible. Check names and parameters are unchanged.

Config validation is now strict#

Two changes that may surface pre-existing issues in your config:

  1. Check name validation: Misspelled check names in your config (e.g. check_modle_access instead of check_model_access) now produce an error instead of being silently ignored.
  2. Config parse errors: Previously, some config file parsing errors were silently swallowed. They now produce clear error messages with line numbers.

If your config was working correctly before, no action is needed.

New: dbt-bouncer.toml support#

You can now use dbt-bouncer.toml as an alternative config format alongside YAML.

CLI changes#

New run subcommand#

The default behaviour (running checks) is now also available as an explicit run subcommand. Both work:

# These are equivalent:
dbt-bouncer --config-file dbt-bouncer.yml
dbt-bouncer run --config-file dbt-bouncer.yml

New CLI features#

  • dbt-bouncer list --output-format json — machine-readable check listing
  • dbt-bouncer run --dry-run — preview which checks would run without executing them
  • Rich-formatted table output for artifact parsing and results

Click → Typer#

The CLI framework changed from Click to Typer. If you were relying on Click-specific behaviour in wrapper scripts, review the Typer docs. The command-line interface is otherwise the same.

One notable difference: boolean flags now use --flag / --no-flag syntax instead of --flag true/false:

- dbt-bouncer --create-pr-comment-file false
+ dbt-bouncer --no-create-pr-comment-file

The GitHub Action handles this automatically — no changes needed if you use the action.

Dependency changes#

Removed dependencies#

The following are no longer installed with dbt-bouncer. If you relied on them transitively, add them to your own requirements.txt:

Removed Replacement
click typer (included)
dbt-artifacts-parser Internal parser (no action needed)
progress rich (included)
requests Not needed
tabulate rich (included)

New dependencies#

Package Version
typer >=0.12, <1
rich >=13, <15
orjson >=3, <4

Python API changes#

Import path changes#

# v2.x
from dbt_bouncer.resource_type import ResourceType

# v3.0.0
from dbt_bouncer import ResourceType
# or
from dbt_bouncer.enums import ResourceType

The dbt_bouncer.resource_type module no longer exists.

New exports#

from dbt_bouncer import (
    CheckOutcome,      # FAILED, SUCCESS
    CheckSeverity,     # ERROR, WARN
    ConfigFileName,    # DBT_BOUNCER_TOML, DBT_BOUNCER_YML, PYPROJECT_TOML
    Materialization,   # EPHEMERAL, INCREMENTAL, TABLE, VIEW
    ResourceType,
    run_bouncer,
)

Module structure changes#

v2.x v3.0.0
dbt_bouncer.resource_type Removed → dbt_bouncer.enums
checks/manifest/check_models.py Split into checks/manifest/models/{access,code,columns,...}.py
checks/manifest/check_sources.py Split into checks/manifest/sources/ subpackage
checks/manifest/check_columns.py Split into checks/manifest/columns/ subpackage
dbt_bouncer.check_decorator (new)
dbt_bouncer.testing (new)
dbt_bouncer.enums (new)

Migrating custom checks#

v2.x: Class-based checks#

from dbt_bouncer.checks.common import BaseCheck

class CheckModelAccess(BaseCheck):
    access: Literal["private", "protected", "public"]
    model: DbtBouncerModelBase | None = Field(default=None)
    name: Literal["check_model_access"]

    def execute(self) -> None:
        assert self.model is not None
        if self.model.access.value != self.access:
            raise DbtBouncerFailedCheckError(
                f"Model `{self.model.name}` has access `{self.model.access.value}`, expected `{self.access}`."
            )

v3.0.0: Decorator-based checks#

from dbt_bouncer.check_decorator import check, fail

@check
def check_model_access(model, *, access: str):
    """Each model should have the specified access level."""
    if model.access and model.access.value != access:
        fail(
            f"Model `{model.name}` has access `{model.access.value}`, expected `{access}`."
        )

Key differences:

  1. No class inheritance — use the @check decorator on a function
  2. No execute() method — the function body is the check logic
  3. No name field — inferred from the function name
  4. No iterate_over ClassVar — inferred from the first parameter name (e.g. model → iterates over models)
  5. fail() instead of raising exceptions — call fail("message") to report failures
  6. Parameters are keyword-only — use * separator after the resource parameter

Plugin registration#

Custom check packages must now register via entry points:

# pyproject.toml of your custom checks package
[project.entry-points."dbt_bouncer.checks"]
my_checks = "my_package.checks"

Testing custom checks#

from dbt_bouncer.testing import check_fails, check_passes

def test_check_model_access_pass():
    check_passes(
        check_model_access,
        model={"name": "my_model", "access": {"value": "private"}},
        access="private",
    )

def test_check_model_access_fail():
    check_fails(
        check_model_access,
        model={"name": "my_model", "access": {"value": "public"}},
        access="private",
    )

New checks in v3.0.0#

The following checks are new in this release:

  • check_model_columns_have_relationship_tests — verify columns have relationship tests
  • check_model_hard_coded_references — detect hard-coded references in model SQL
  • check_seed_column_types — validate seed column types
  • check_seed_has_unit_tests — verify seeds have unit tests
  • check_snapshot_description_populated — require snapshot descriptions
  • check_test_has_meta_keys — require specific meta keys on tests

New features#

  • JSON Schema for config files — enables IDE autocomplete and validation
  • dbt-bouncer.toml config format support
  • --dry-run flag — preview checks without running them
  • list --output-format json — machine-readable output
  • Entry-points plugin system — third-party check packages
  • Rich table output — improved terminal formatting

Getting help#

If you run into issues upgrading:

  1. Check that your config file has no misspelled check names
  2. Update custom check imports per the table above
  3. Open an issue at github.com/godatadriven/dbt-bouncer/issues