Check five places in every pull request: Python requirements and constraints, DAG files, dbt package files, Spark submit options and jars, and warehouse function definitions. A data repo spreads dependencies across all of them, so a review that reads only one manifest misses the rest.
Why data repos are different
An application repo usually has one manifest per language. A data engineering repo mixes orchestration code, SQL projects, Spark jobs and warehouse objects, and each has its own way to pull in code.
- Airflow environments are built from a requirements list and the project's constraint file for a given version. Tasks can also install packages themselves, depending on the operator.
- dbt projects list packages in a package file and record resolved versions in a lock file.
- Spark jobs pull code through jars, Maven coordinates, extra repositories and Python archives.
- Warehouse Python functions list packages in their definitions.
A reviewer who knows where to look catches far more.
The checklist
- Python requirements. Is every new package pinned to an exact version? Does the file still install with the Airflow constraint file for your version and Python? Did pip check pass in CI?
- DAG files. Are there new top-level imports? Parsing a DAG file runs its top-level code, and the Airflow docs advise keeping that minimal. Can the import move inside the task?
- Run-time installs. Does any task, entrypoint or script run an install command at start? The Airflow docs note that virtualenv style tasks need package index access on workers.
- dbt packages. Is each Git package pinned to a tag or full commit hash? Is the lock file updated in the same change? The docs say unpinned Git packages raise a warning. Did anyone read the package's macros?
- Spark submit. New jars, new package coordinates, or a new repository option? Does any URI carry credentials? The Spark docs warn about that.
- JDBC drivers. Where does the new jar come from, and is the version and hash recorded?
- Warehouse functions. Does a function definition add a package? Snowflake's docs say it does not check or curate the security of external packages.
- Lock and image files. Does the lock file diff match the intent of the change? A one line bump can move dozens of transitive packages.
- Scan result. Does the scan of the change show new advisories? For each, is the vulnerable code reachable from your jobs?
- Owner and rollback. Who owns the new dependency, and how do you remove it?
How to run the review quickly
Put the checklist in your pull request template as boxes. Automate what you can: pinning checks, pip check, a scan, and a comparison of the package inventory before and after. Reserve human time for judgment calls, such as "why do we need this package at all?"
What a good result looks like
A reviewer should be able to say, in one sentence, what changed in the dependency set, why, and what would happen if it were reverted. If nobody can, the change is not ready.
Try it yourself
Click through it at your own pace, or open it full screen. See how a check result appears on the pull request before merge.
Safeguard's policies and gates can run these checks on pull requests, and its SBOM and dependency scanning and reachability analysis supply the findings. The free scan at https://gold.safeguard.sh/scan is a quick way to see what it reports for a repository.
Quick check
Do I need all ten checks on every pull request?
No. Most changes touch one or two places. The list tells you which to apply, and automation covers the repeatable ones.
Who should review dependency changes in a data repo?
Someone who knows the platform that consumes them, plus an owner for the security view. Make that a named role.
Sources
Last reviewed: 19 October 2026.