dbt / Advanced: evidence, isolation and recoverable releases / Lesson 14
CI, deferral and environment isolation
Use prior state to reduce test scope while preserving explicit input resolution, runtime permissions and publication ownership.
On this page
Lesson goals
- Separate comparison state from deferred applied relations.
- Review mixed-environment reads and denied writes.
A CI baseline is evidence, not a magic production label
Slim CI can compare changed project logic with a prior manifest and build a justified subset in an isolated target. The baseline must identify the intended project revision, artifact schema and applied environment. A file named prod-manifest does not prove its provenance. Source-data changes and current warehouse state are different from code comparison. Store the baseline read-only in a location separate from newly generated target artifacts. If the comparison input is overwritten during the invocation, later decisions can refer to a different state than the reviewer approved.
A narrow build can still read outside its target
The command text selects modified nodes and descendants and enables deferral using a fictional artifact path. It is not executed. By documented default, eligible unselected refs can defer when the relation is absent in the current target; favor-state changes that preference. Ephemeral resources are handled differently and are not deferred like physical relations. A selected model normally builds in its configured CI target while reading approved existing parents elsewhere. Inspect the resolved names before authorized execution rather than assuming every ref points to CI or every deferred reference points to one production snapshot.
dbt build --select "state:modified+" --state lab-baseline --defer
Illustrative CLI text only. It can create and test target resources if actually run, so this course does not invoke it.
Logical comparison and applied deferral may use different evidence
The framework supports separate state and defer-state contexts for suitable workflows. One can compare logic against a reviewed revision while resolving unselected parents from a different applied environment. This flexibility also increases the need for provenance and compatibility checks. A local review manifest below separates these concepts without supplying real paths or credentials. Relationship tests can then span development and deferred parents, producing a meaningful but mixed-population assertion. Define whether that is the desired test question and document any environment-specific row limits that make the populations incomparable.
{"scope":"synthetic CI review","comparison_state":"reviewed logical revision","deferred_state":"approved applied parent relations","write_target":"isolated CI namespace","required_checks":["resolved inputs","denied production writes","artifact compatibility"]}
A local environment-review model, not a profiles.yml connection or an executed CI job.
Isolation requires actual permission boundaries
A schema naming convention is not a database security policy. The CI principal should have only the approved source reads and isolated writes needed by the workflow, with production writes denied. Hooks, run-operation macros and failure-storage relations can introduce writes beyond a model’s visible SELECT. Review those paths and temporary schemas explicitly. Environment variables can supply configuration, but secret handling and redaction depend on supported contexts and deployment controls. Do not embed credentials in manifests, examples or logs. A selector and model-access modifier cannot replace actual warehouse authorization.
CI success must include scope and recovery meaning
Verify selected nodes, indirect tests, resolved input relations, required assertions and output namespace before promoting code. A model built successfully can coexist with failed downstream tests or incomplete source coverage. Publication and cleanup need their own owner, retention and recovery policy. Preserve the approved artifacts for audit without leaking sensitive SQL or metadata. This course creates no CI job, role, schema or cloud environment and runs no state/defer command. Local checks exercise only graph selection and the review JSON, not warehouse isolation, permission denial or platform orchestration.
Common errors and fixes
Deferred refs are assumed to read only the CI schema
- Why it happens
- Execution target and reference-resolution context were conflated.
- How to fix it
- Inspect actual resolved relations and deferral conditions.
- Prevent it next time
- Include mixed-environment inputs in CI review evidence.
A state baseline is overwritten by new output
- Why it happens
- Comparison and target artifact directories were shared.
- How to fix it
- Keep immutable baseline evidence separate from invocation output.
- Prevent it next time
- Record artifact provenance and paths before execution.
CI can modify production through a hook
- Why it happens
- Only visible model SQL was reviewed for write scope.
- How to fix it
- Review hooks, operations and grants under the actual principal.
- Prevent it next time
- Verify denied production writes independently of naming conventions.
Check your understanding
1. Does --defer mean every unselected parent always comes from the baseline?
Show worked solution
No. Default resolution conditions and current-target existence matter, and favor-state can alter preference. Ephemeral resources have different behavior. Verify the selected version’s rules and actual relation names before treating CI results as comparisons over one known input population.
2. Why test denied writes if the CI schema name is unique?
Show worked solution
A name does not constrain the credential’s authority. Macros, hooks or misconfigured relations can target other locations. Use real permission boundaries in an authorized environment and keep that evidence separate from local selector or JSON validation.
Key takeaways
- Comparison state, applied state and write target are separate contexts.
- A safe CI scope needs graph, relation and permission evidence.