Skip to main content

CI Integration

The check

dfmt check .

Exit 0 if everything is formatted, 1 if anything is not. Nothing is ever written. The summary is one line:

2 files checked, 2 would be reformatted, 0 already formatted, 0 not assessed (parse warnings), 0 failed (148ms)

Each counter is a different outcome, and two of them are easy to conflate:

  • would be reformatted — dfmt formatted the file and the result differs from what is on disk.
  • not assessed — dfmt declined to judge: it could not parse the file under the declared dialect, or the file is a template and no dbt project was found to evaluate it against.
  • failed — the run itself broke: unreadable file, bad config.

check fails on "not assessed" as well as on "would be reformatted". A file nobody could assess is not a passing file; if it were treated as passing, a dialect mistake in dlab.json would look like a clean repository. When files go unassessed, dfmt names the declared dialect in a hint, because the usual cause is that the dialect is wrong rather than the SQL.

Showing the diff in the log

check says which files are wrong. diff says what is wrong with them:

dfmt diff .

They are separate runs — the output modes are mutually exclusive — so a job that wants both runs check to set the exit code, and diff when it fails.

GitHub Actions

name: SQL format
on: [pull_request]

jobs:
dfmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # --changed-since needs history

# Install dfmt: download the release archive for the runner's platform
# (dlab-x86_64-pc-linux.tar.gz) and put the binary on PATH.

- run: dfmt check .
- if: failure()
run: dfmt diff .

fetch-depth: 0 matters only if you use --changed-since; the default shallow checkout has no origin/main to diff against.

Only what the PR touched

dfmt check --changed-since origin/main

--changed-since asks git for changed .sql files and then intersects them with the include/exclude patterns in dlab.json, so files outside your project are not checked even if they changed.

This is a smaller check, not a weaker one — but it does mean a file that was already unformatted before the PR stays unformatted. Run the full dfmt check . on the default branch if you want the whole repository held to the standard.

Pre-commit

repos:
- repo: local
hooks:
- id: dfmt
name: dfmt
entry: dfmt check
language: system
types: [sql]

To format instead of complain, make the entry dfmt write and let the hook restage.

dbt projects

Package macros have to be present before dfmt can evaluate a template that calls them, so dbt deps comes first:

      - run: dbt deps
- run: dfmt check .

Without it, dfmt stops the run and tells you: a project whose packages.yml is uninstalled is misconfigured, and formatting its models anyway would expand every missing macro to nothing and format the result. That is a wrong answer dressed as a successful one, so it is an error and not a warning.