Skip to content

Running this package as a CI check#

Much better than in version 1: check only what a pull request changes

In version 1 the whole project was evaluated on every run, so a CI check was only usable once every existing violation was fixed or accepted. With version 2 you can run the checks on the modified resources only (dbt check --select state:modified): a pull request only sees the violations it introduces, and the existing ones don't block anyone (the checks on sources can't be scoped yet, see the warning below). You can adopt the package in CI today and fix the backlog at your own pace. See only reporting the violations on the modified resources.

You can use this package as a CI check to ensure code changes don't introduce new misalignments. To fail on any violation of the whole project, first address the current misalignments (either by fixing them or accepting them as exceptions); to fail only on the violations a change introduces, select the modified resources.

Since the rules are native dbt checks, there is nothing to build in your warehouse: the checks run when the project is parsed, and a check configured with severity: error makes the command fail when it finds violations.

1. Make the checks fail in CI#

By default, the checks in this package are configured with "warn" severity: they report the violations but don't make dbt check or dbt build fail. You can set the severity for the whole package, for a category of checks or for an individual check in your dbt_project.yml:

dbt_project.yml
checks:
  dbt_project_evaluator:
    +severity: error              # every check
    documentation:
      +severity: warn             # but only warn for a whole category
      fct_undocumented_models:
        +severity: error          # except for this one

To only make the checks fail in CI, you can use an environment variable, set to "error" in the CI environment and left unset everywhere else:

dbt_project.yml
checks:
  dbt_project_evaluator:
    +severity: "{{ env_var('DBT_PROJECT_EVALUATOR_SEVERITY', 'warn') }}"

Note

You can follow a similar process to disable checks in some environments, using +enabled instead of +severity.

2. Run the checks for each pull request#

The checks are executed at the beginning of dbt build, so a CI job running dbt build already evaluates your project. When a check with severity: error finds violations, dbt build fails before building any model.

You can also run only the checks, without building anything, with

dbt check

The command exits with a non-zero code when a check configured with severity: error returns rows.

Only reporting the violations on the modified resources#

Each check returns the resource to fix in the column unique_id, which allows --select to restrict the violations reported to the selected resources. Combined with state:modified, which compares your project with the artifacts of your main branch, this reports the violations introduced by the pull request and ignores the existing ones:

dbt check --select state:modified --state path/to/main/target   # GitHub Actions, local...
dbt check --select state:modified                               # dbt platform CI job

--state is the folder with the artifacts of your main branch. In a CI job on the dbt platform, the state of the production environment is provided to the job through deferral, so you don't pass --state. Anywhere else, you have to produce the artifacts of your main branch and pass their location, as in the example below.

For example, after modifying the model stg_orders, the checks that look at individual resources (fct_undocumented_models, fct_missing_primary_key_tests...) only report stg_orders.

Note

fct_documentation_coverage and fct_test_coverage measure the whole project and not individual resources. They are configured with selection_filter_on: none and are therefore always evaluated on the entire project, whatever --select is set to.

Warning

With dbt 2.0.6, dbt check --select cannot scope source rows (dbt-labs/dbt#16554), so state:modified does not pick up a changed source. The checks that report sources (fct_unused_sources, fct_sources_without_freshness, fct_undocumented_source_tables, fct_undocumented_sources, fct_duplicate_sources, fct_source_directories, fct_source_fanout) therefore report nothing when a selector is set. Run them without --select (for example in a separate, non-blocking step) to catch source violations.

Example with GitHub Actions#

The following workflow parses the base branch of the pull request to get a manifest to compare to, then runs the checks on the modified resources:

.github/workflows/dbt_project_evaluator.yml
name: dbt project evaluator

on: pull_request

jobs:
  checks:
    runs-on: ubuntu-latest
    env:
      DBT_PROJECT_EVALUATOR_SEVERITY: error
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - run: pip install "dbt>=2.0.0,<3.0.0"

      - name: Parse the base branch to get the state to compare to
        run: |
          git worktree add ../base "origin/${{ github.base_ref }}"
          cd ../base
          dbt deps
          dbt parse

      - run: dbt deps

      - name: Check the modified resources
        run: dbt check --select state:modified --state ../base/target

Note

The dbt parse and dbt check commands need a valid profile for your project. On the dbt platform, none of the "base branch" steps of this example are needed: run dbt check --select state:modified in a CI job set up with deferral and the state comes from the job's environment.