Repository hygiene · rule dbt-packages-unlocked
dbt packages.yml: how it works and why to lock it
packages.yml lists the dbt packages your project installs. It sits beside dbt_project.yml. dbt deps reads it, installs each package and records what it resolved in package-lock.yml.
A Metacenta review checks this under the rule dbt package versions are locked. Everything below applies whether or not you ever commission one.
What packages.yml does
Packages install into dbt_packages/, which git ignores. Their models and macros then become part of your project.
How to add a package
Add an entry, then run dbt deps. Hub packages need a version, and they let dbt deduplicate dependencies that two packages share.
packages:
- package: dbt-labs/dbt_utils
version: 1.3.0
- git: "https://github.com/example-org/example_package.git"
revision: 0.9.2
- local: relative/path/to/package
What dbt deps and package-lock.yml do
dbt deps creates or updates package-lock.yml. If packages.yml hasn't changed, later installs use the lock file. A version range pins to the latest matching release, and a branch pins to its head commit.
Newer versions aren't picked up until you run dbt deps --upgrade.
packages.yml or dependencies.yml
Use dependencies.yml for dbt Mesh project dependencies, or to keep packages and projects in one file. Use packages.yml if you need Jinja on dbt v1, such as a git token from an environment variable.
See dbt's packages docs for the other entry types.
What this rule checks
This rule flags a dbt project whose packages.yml or dependencies.yml has no package-lock.yml beside it. It passes if every package is pinned exactly: one version, a commit SHA, a version tag or a local path. Version ranges, git branches and packages with no version float, and we name those. Only the root-most dbt project is judged.
Why it matters
Package versions resolve fresh on every install. Two CI runs a week apart can build the same project against different package code. A macro can change behaviour with nothing in the repository's history to show it.
How to fix it
Commit the dbt package lockfile. Commit the package-lock.yml that dbt deps already writes, and change it only on purpose.
Before:
# packages.yml, with no package-lock.yml beside it
packages:
- package: dbt-labs/dbt_utils
version: [">=1.0.0", "<2.0.0"]
After:
# package-lock.yml, written by dbt deps and committed
packages:
- package: dbt-labs/dbt_utils
version: 1.3.0
sha1_hash: <written by dbt deps>
When it is fine to leave
A project that pins every package to one exact version already passes, because it resolves the same way each time. Another sub-project in the repository, such as integration_tests/, is named in the finding as not examined.
What we need to check it
The repository's file list, the packages file, and the dbt version from manifest.json. package-lock.yml exists from dbt 1.7, so without a manifest we decline, and older projects aren't judged. We also decline if the listing was truncated or the packages file could not be read. If it wasn't fetched at all, we report the missing lockfile without judging the pins.