Skip to content

Versioning#

Note

The below checks require manifest.json to be present.

Checks related to model versioning.

Functions:

Name Description
check_model_latest_version_specified

Check that the latest_version attribute of the model is set.

check_model_version_allowed

Check that the version of the model matches the supplied regex pattern.

check_model_version_pinned_in_ref

Check that the version of the model is always specified in downstream nodes.

check_model_latest_version_specified #

Check that the latest_version attribute of the model is set.

Receives at execution time:

Name Type Description
model ModelNode

The ModelNode object to check.

Other Parameters (passed via config file):

Name Type Description
description str | None

Description of what the check does and why it is implemented.

exclude str | None

Regex pattern to match the model path. Model paths that match the pattern will not be checked.

include str | None

Regex pattern to match the model path. Only model paths that match the pattern will be checked.

materialization Literal[ephemeral, incremental, table, view] | None

Limit check to models with the specified materialization.

severity Literal[error, warn] | None

Severity level of the check. Default: error.

Example(s):

manifest_checks:
    - name: check_model_latest_version_specified
      include: ^models/marts

Source code in src/dbt_bouncer/checks/manifest/models/versioning.py
@check
def check_model_latest_version_specified(model):
    """Check that the `latest_version` attribute of the model is set.

    Receives:
        model (ModelNode): The ModelNode object to check.

    Other Parameters:
        description (str | None): Description of what the check does and why it is implemented.
        exclude (str | None): Regex pattern to match the model path. Model paths that match the pattern will not be checked.
        include (str | None): Regex pattern to match the model path. Only model paths that match the pattern will be checked.
        materialization (Literal["ephemeral", "incremental", "table", "view"] | None): Limit check to models with the specified materialization.
        severity (Literal["error", "warn"] | None): Severity level of the check. Default: `error`.

    Example(s):
        ```yaml
        manifest_checks:
            - name: check_model_latest_version_specified
              include: ^models/marts
        ```

    """
    if model.latest_version is None:
        fail(f"`{model.name}` does not have a specified `latest_version`.")

check_model_version_allowed #

Check that the version of the model matches the supplied regex pattern.

Parameters:

Name Type Description Default
version_pattern str

Regexp the version must match.

required

Receives at execution time:

Name Type Description
model ModelNode

The ModelNode object to check.

Other Parameters (passed via config file):

Name Type Description
description str | None

Description of what the check does and why it is implemented.

exclude str | None

Regex pattern to match the model path. Model paths that match the pattern will not be checked.

include str | None

Regex pattern to match the model path. Only model paths that match the pattern will be checked.

materialization Literal[ephemeral, incremental, table, view] | None

Limit check to models with the specified materialization.

severity Literal[error, warn] | None

Severity level of the check. Default: error.

Example(s):

manifest_checks:
    - name: check_model_version_allowed
      include: ^models/marts
      version_pattern: >- # Versions must be numeric
        [0-9]\d*
    - name: check_model_version_allowed
      include: ^models/marts
      version_pattern: ^(stable|latest)$ # Version can be "stable" or "latest", nothing else is permitted

Source code in src/dbt_bouncer/checks/manifest/models/versioning.py
@check
def check_model_version_allowed(model, *, version_pattern: str):
    r"""Check that the version of the model matches the supplied regex pattern.

    Parameters:
        version_pattern (str): Regexp the version must match.

    Receives:
        model (ModelNode): The ModelNode object to check.

    Other Parameters:
        description (str | None): Description of what the check does and why it is implemented.
        exclude (str | None): Regex pattern to match the model path. Model paths that match the pattern will not be checked.
        include (str | None): Regex pattern to match the model path. Only model paths that match the pattern will be checked.
        materialization (Literal["ephemeral", "incremental", "table", "view"] | None): Limit check to models with the specified materialization.
        severity (Literal["error", "warn"] | None): Severity level of the check. Default: `error`.

    Example(s):
        ```yaml
        manifest_checks:
            - name: check_model_version_allowed
              include: ^models/marts
              version_pattern: >- # Versions must be numeric
                [0-9]\d*
            - name: check_model_version_allowed
              include: ^models/marts
              version_pattern: ^(stable|latest)$ # Version can be "stable" or "latest", nothing else is permitted
        ```

    """
    compiled = compile_pattern(version_pattern.strip())
    if model.version and (compiled.match(str(model.version)) is None):
        fail(
            f"Version `{model.version}` in `{model.name}` does not match the supplied regex `{version_pattern.strip()})`."
        )

check_model_version_pinned_in_ref #

Check that the version of the model is always specified in downstream nodes.

Receives at execution time:

Name Type Description
manifest_obj ManifestObject

The ManifestObject object parsed from manifest.json.

model ModelNode

The ModelNode object to check.

Other Parameters (passed via config file):

Name Type Description
description str | None

Description of what the check does and why it is implemented.

exclude str | None

Regex pattern to match the model path. Model paths that match the pattern will not be checked.

include str | None

Regex pattern to match the model path. Only model paths that match the pattern will be checked.

materialization Literal[ephemeral, incremental, table, view] | None

Limit check to models with the specified materialization.

severity Literal[error, warn] | None

Severity level of the check. Default: error.

Example(s):

manifest_checks:
    - name: check_model_version_pinned_in_ref
      include: ^models/marts

Source code in src/dbt_bouncer/checks/manifest/models/versioning.py
@check
def check_model_version_pinned_in_ref(model, ctx):
    """Check that the version of the model is always specified in downstream nodes.

    Receives:
        manifest_obj (ManifestObject): The ManifestObject object parsed from `manifest.json`.
        model (ModelNode): The ModelNode object to check.

    Other Parameters:
        description (str | None): Description of what the check does and why it is implemented.
        exclude (str | None): Regex pattern to match the model path. Model paths that match the pattern will not be checked.
        include (str | None): Regex pattern to match the model path. Only model paths that match the pattern will be checked.
        materialization (Literal["ephemeral", "incremental", "table", "view"] | None): Limit check to models with the specified materialization.
        severity (Literal["error", "warn"] | None): Severity level of the check. Default: `error`.

    Example(s):
        ```yaml
        manifest_checks:
            - name: check_model_version_pinned_in_ref
              include: ^models/marts
        ```

    """
    manifest_obj = ctx.manifest_obj
    child_map = manifest_obj.manifest.child_map
    if child_map and model.unique_id in child_map:
        downstream_models = [
            x for x in child_map[model.unique_id] if x.startswith("model.")
        ]
    else:
        downstream_models = []

    downstream_models_with_unversioned_refs: list[str] = []
    for m in downstream_models:
        node = manifest_obj.manifest.nodes.get(m)
        refs = getattr(node, "refs", None)
        if node and refs and isinstance(refs, list):
            downstream_models_with_unversioned_refs.extend(
                m
                for ref in refs
                if getattr(ref, "name", None) == model.unique_id.split(".")[-1]
                and not getattr(ref, "version", None)
            )

    if downstream_models_with_unversioned_refs:
        fail(
            f"`{model.name}` is referenced without a pinned version in downstream models: {downstream_models_with_unversioned_refs}."
        )