dbt-data-contracts 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dbt_data_contracts-0.1.0/.cursor/commands/add-tests.md +8 -0
- dbt_data_contracts-0.1.0/.cursor/commands/implement-feature.md +29 -0
- dbt_data_contracts-0.1.0/.cursor/commands/review-change.md +21 -0
- dbt_data_contracts-0.1.0/.cursor/commands/update-docs.md +7 -0
- dbt_data_contracts-0.1.0/.cursor/rules/agent-workflow.mdc +22 -0
- dbt_data_contracts-0.1.0/.cursor/rules/architecture.mdc +20 -0
- dbt_data_contracts-0.1.0/.cursor/rules/cli.mdc +15 -0
- dbt_data_contracts-0.1.0/.cursor/rules/python.mdc +24 -0
- dbt_data_contracts-0.1.0/.cursor/rules/security.mdc +18 -0
- dbt_data_contracts-0.1.0/.cursor/rules/testing.mdc +20 -0
- dbt_data_contracts-0.1.0/.gitattributes +2 -0
- dbt_data_contracts-0.1.0/.gitignore +33 -0
- dbt_data_contracts-0.1.0/AGENTS.md +92 -0
- dbt_data_contracts-0.1.0/CONTRIBUTING.md +34 -0
- dbt_data_contracts-0.1.0/LICENSE +21 -0
- dbt_data_contracts-0.1.0/PKG-INFO +210 -0
- dbt_data_contracts-0.1.0/README.md +178 -0
- dbt_data_contracts-0.1.0/docs/adr/0001-canonical-contract-model.md +24 -0
- dbt_data_contracts-0.1.0/docs/adr/0002-registry-abstraction.md +21 -0
- dbt_data_contracts-0.1.0/docs/adr/0003-immutable-contract-versions.md +22 -0
- dbt_data_contracts-0.1.0/docs/adr/README.md +32 -0
- dbt_data_contracts-0.1.0/docs/architecture.md +89 -0
- dbt_data_contracts-0.1.0/docs/compatibility-rules.md +37 -0
- dbt_data_contracts-0.1.0/docs/discovery.md +20 -0
- dbt_data_contracts-0.1.0/docs/domain-model.md +61 -0
- dbt_data_contracts-0.1.0/docs/project-state.md +53 -0
- dbt_data_contracts-0.1.0/docs/registry.md +29 -0
- dbt_data_contracts-0.1.0/docs/spec.md +1270 -0
- dbt_data_contracts-0.1.0/examples/consumer/README.md +11 -0
- dbt_data_contracts-0.1.0/examples/consumer/data-contract-consumers.yml +15 -0
- dbt_data_contracts-0.1.0/examples/producer/README.md +14 -0
- dbt_data_contracts-0.1.0/examples/producer/dbt_project.yml +13 -0
- dbt_data_contracts-0.1.0/examples/producer/models/fct_orders.sql +5 -0
- dbt_data_contracts-0.1.0/examples/producer/models/schema.yml +27 -0
- dbt_data_contracts-0.1.0/plans/README.md +15 -0
- dbt_data_contracts-0.1.0/plans/active/vertical-slice-02.md +61 -0
- dbt_data_contracts-0.1.0/plans/backlog/azure-devops-discovery.md +21 -0
- dbt_data_contracts-0.1.0/plans/backlog/local-discovery.md +20 -0
- dbt_data_contracts-0.1.0/plans/backlog/pr-annotations.md +12 -0
- dbt_data_contracts-0.1.0/plans/backlog/remote-registry.md +15 -0
- dbt_data_contracts-0.1.0/plans/completed/vertical-slice-01.md +86 -0
- dbt_data_contracts-0.1.0/pyproject.toml +81 -0
- dbt_data_contracts-0.1.0/scripts/demo.sh +51 -0
- dbt_data_contracts-0.1.0/scripts/dev-check.sh +16 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/__init__.py +3 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/cli/__init__.py +5 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/cli/app.py +56 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/cli/check.py +112 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/cli/consumer.py +107 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/cli/ingest.py +64 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/cli/publish.py +97 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/cli/registry.py +62 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/compatibility/__init__.py +11 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/compatibility/engine.py +119 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/compatibility/rules/columns.py +79 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/compatibility/rules/consumers.py +76 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/compatibility/rules/metadata.py +29 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/compatibility/rules/nullability.py +45 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/compatibility/types.py +102 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/consumers/__init__.py +9 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/consumers/parser.py +112 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/consumers/resolver.py +20 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/dbt/__init__.py +11 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/dbt/ingestion.py +170 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/dbt/manifest.py +42 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/domain/__init__.py +51 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/domain/compatibility.py +66 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/domain/consumers.py +41 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/domain/contracts.py +49 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/domain/provenance.py +61 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/domain/versions.py +140 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/exceptions.py +37 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/registry/__init__.py +9 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/registry/protocol.py +61 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/registry/schema.py +78 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/registry/sqlite.py +229 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/reporting/__init__.py +9 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/reporting/console.py +131 -0
- dbt_data_contracts-0.1.0/src/dbt_contracts/reporting/json.py +16 -0
- dbt_data_contracts-0.1.0/tests/e2e/test_contract_lifecycle.py +123 -0
- dbt_data_contracts-0.1.0/tests/fixtures/consumers/finance.yml +15 -0
- dbt_data_contracts-0.1.0/tests/fixtures/consumers/growth.yml +12 -0
- dbt_data_contracts-0.1.0/tests/fixtures/consumers/version_only.yml +7 -0
- dbt_data_contracts-0.1.0/tests/fixtures/manifests/breaking_orders_manifest.json +56 -0
- dbt_data_contracts-0.1.0/tests/fixtures/manifests/compatible_minor_manifest.json +51 -0
- dbt_data_contracts-0.1.0/tests/fixtures/manifests/patch_metadata_manifest.json +56 -0
- dbt_data_contracts-0.1.0/tests/fixtures/manifests/private_model_manifest.json +29 -0
- dbt_data_contracts-0.1.0/tests/fixtures/manifests/v1_orders_manifest.json +59 -0
- dbt_data_contracts-0.1.0/tests/integration/registry/test_sqlite_registry.py +109 -0
- dbt_data_contracts-0.1.0/tests/unit/compatibility/test_compatibility_rules.py +144 -0
- dbt_data_contracts-0.1.0/tests/unit/compatibility/test_type_compatibility.py +47 -0
- dbt_data_contracts-0.1.0/tests/unit/consumers/test_consumer_parser.py +47 -0
- dbt_data_contracts-0.1.0/tests/unit/dbt/test_manifest_ingestion.py +62 -0
- dbt_data_contracts-0.1.0/tests/unit/domain/test_domain_models.py +72 -0
- dbt_data_contracts-0.1.0/tests/unit/domain/test_versions.py +89 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Add or improve tests for the specified behavior.
|
|
2
|
+
|
|
3
|
+
Conventions:
|
|
4
|
+
- Unit tests under `tests/unit/` for domain models, SemVer rules, compatibility rules, type normalization, consumer expectation evaluation, and manifest parsing.
|
|
5
|
+
- Integration tests under `tests/integration/` for SQLite registry, adapter composition, and discovery.
|
|
6
|
+
- End-to-end tests under `tests/e2e/` for complete CLI workflows with exit codes tested explicitly.
|
|
7
|
+
- Use small synthetic fixtures under `tests/fixtures/`.
|
|
8
|
+
- Ensure all tests pass without network access or real provider credentials.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Implement the requested feature using the repository's agent workflow.
|
|
2
|
+
|
|
3
|
+
Before coding:
|
|
4
|
+
|
|
5
|
+
1. read `AGENTS.md`
|
|
6
|
+
2. read `docs/project-state.md`
|
|
7
|
+
3. read the relevant active plan
|
|
8
|
+
4. inspect relevant ADRs
|
|
9
|
+
5. inspect existing tests
|
|
10
|
+
|
|
11
|
+
Confirm the feature fits the current plan. If substantial work is missing from the plan, update the plan first.
|
|
12
|
+
|
|
13
|
+
Implement a vertical slice rather than disconnected layers.
|
|
14
|
+
|
|
15
|
+
Add tests before or alongside implementation.
|
|
16
|
+
|
|
17
|
+
Before completion:
|
|
18
|
+
|
|
19
|
+
- run validation
|
|
20
|
+
- update affected docs
|
|
21
|
+
- add an ADR if architecture changed
|
|
22
|
+
- update `docs/project-state.md`
|
|
23
|
+
|
|
24
|
+
Summarize:
|
|
25
|
+
- what changed
|
|
26
|
+
- tests added
|
|
27
|
+
- commands run
|
|
28
|
+
- architectural decisions
|
|
29
|
+
- remaining limitations
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Review the current change against:
|
|
2
|
+
|
|
3
|
+
- `AGENTS.md`
|
|
4
|
+
- architecture boundaries
|
|
5
|
+
- active plan acceptance criteria
|
|
6
|
+
- compatibility semantics
|
|
7
|
+
- security rules
|
|
8
|
+
- tests
|
|
9
|
+
|
|
10
|
+
Look specifically for:
|
|
11
|
+
|
|
12
|
+
- infrastructure leaking into domain
|
|
13
|
+
- mutable published versions
|
|
14
|
+
- provider-specific coupling
|
|
15
|
+
- hidden network calls
|
|
16
|
+
- missing error handling
|
|
17
|
+
- compatibility changes without tests
|
|
18
|
+
- CLI logic containing domain behavior
|
|
19
|
+
- downstream repository assumptions
|
|
20
|
+
|
|
21
|
+
Report issues by severity and suggest concrete fixes.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Update repository documentation to reflect recent implementation changes:
|
|
2
|
+
|
|
3
|
+
1. Update `docs/project-state.md` with working components and next steps.
|
|
4
|
+
2. Update `docs/architecture.md` if architectural components or data flow changed.
|
|
5
|
+
3. Update `docs/domain-model.md` or `docs/compatibility-rules.md` if domain models or rules evolved.
|
|
6
|
+
4. Record new architectural decisions in `docs/adr/`.
|
|
7
|
+
5. Update `README.md` quickstart or usage examples if CLI commands changed.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Agent implementation workflow
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Implement vertical slices, not disconnected architectural layers.
|
|
7
|
+
|
|
8
|
+
Before starting substantial work:
|
|
9
|
+
|
|
10
|
+
1. read project state (`docs/project-state.md`)
|
|
11
|
+
2. read the active plan (`plans/active/`)
|
|
12
|
+
3. confirm acceptance criteria
|
|
13
|
+
4. inspect relevant tests
|
|
14
|
+
|
|
15
|
+
Do not attempt the entire roadmap in one task.
|
|
16
|
+
|
|
17
|
+
After completing work:
|
|
18
|
+
|
|
19
|
+
1. run validation (`pytest`, `ruff check .`, `ruff format --check .`, `mypy`)
|
|
20
|
+
2. update documentation
|
|
21
|
+
3. update project state
|
|
22
|
+
4. move completed plans when appropriate
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Architectural boundaries for dbt-contracts
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The canonical domain layer must remain infrastructure-independent.
|
|
7
|
+
|
|
8
|
+
Never import dbt, SQLAlchemy, Typer, Azure DevOps SDKs, HTTP clients, or provider-specific objects into `src/dbt_contracts/domain`.
|
|
9
|
+
|
|
10
|
+
Translate external representations into canonical domain models at adapter boundaries.
|
|
11
|
+
|
|
12
|
+
Published contract versions are immutable.
|
|
13
|
+
|
|
14
|
+
Declared consumer expectations are different from observed lineage.
|
|
15
|
+
|
|
16
|
+
A producer compatibility check must not require cloning downstream repositories.
|
|
17
|
+
|
|
18
|
+
Compatibility decisions must produce structured reasons.
|
|
19
|
+
|
|
20
|
+
When an architectural boundary needs to change, create an ADR before implementing the change.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: CLI implementation rules
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
CLI commands orchestrate application and domain behavior; they do not contain core business logic.
|
|
7
|
+
|
|
8
|
+
Use Typer with explicit type annotations.
|
|
9
|
+
|
|
10
|
+
Exit codes must follow standard conventions:
|
|
11
|
+
- 0: compatible / valid / success
|
|
12
|
+
- 1: breaking or invalid compatibility/version gate
|
|
13
|
+
- 2: configuration / parsing / operational error
|
|
14
|
+
|
|
15
|
+
Separate domain results from rendering: CLI commands call domain/application services, then delegate output to `reporting/console.py` or `reporting/json.py`.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Python engineering conventions
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Target Python 3.11+.
|
|
7
|
+
|
|
8
|
+
Use:
|
|
9
|
+
|
|
10
|
+
- Pydantic v2
|
|
11
|
+
- SQLAlchemy 2.x
|
|
12
|
+
- Typer
|
|
13
|
+
- pathlib / PurePosixPath
|
|
14
|
+
- modern type annotations
|
|
15
|
+
|
|
16
|
+
Prefer explicit types over dictionaries.
|
|
17
|
+
|
|
18
|
+
Keep functions small and cohesive.
|
|
19
|
+
|
|
20
|
+
Do not introduce dependencies without explaining why they are necessary.
|
|
21
|
+
|
|
22
|
+
Use dependency injection for infrastructure that needs mocking.
|
|
23
|
+
|
|
24
|
+
Do not catch broad Exception unless translating at an application boundary.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Security rules
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Never commit, log, serialize, or persist credentials.
|
|
7
|
+
|
|
8
|
+
Azure DevOps credentials must come from environment variables or a future credential-provider abstraction.
|
|
9
|
+
|
|
10
|
+
Organization discovery must not execute arbitrary repository code by default.
|
|
11
|
+
|
|
12
|
+
Do not automatically run `dbt build`.
|
|
13
|
+
|
|
14
|
+
Running `dbt parse` against discovered repositories must require explicit permission.
|
|
15
|
+
|
|
16
|
+
Treat repository contents as untrusted input.
|
|
17
|
+
|
|
18
|
+
Validate paths and avoid unsafe filesystem traversal.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Testing conventions
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use pytest.
|
|
7
|
+
|
|
8
|
+
Every compatibility rule requires focused unit tests.
|
|
9
|
+
|
|
10
|
+
Every external provider must be testable without real credentials.
|
|
11
|
+
|
|
12
|
+
Azure DevOps tests must use fixtures, mocks, or fake adapters and must never require a real Azure DevOps organization.
|
|
13
|
+
|
|
14
|
+
Prefer:
|
|
15
|
+
|
|
16
|
+
- unit tests -> domain and rule behavior
|
|
17
|
+
- integration tests -> persistence and adapter composition
|
|
18
|
+
- end-to-end tests -> complete CLI workflows
|
|
19
|
+
|
|
20
|
+
Bug fixes should add a regression test whenever practical.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
.local
|
|
2
|
+
.venv/
|
|
3
|
+
venv/
|
|
4
|
+
ENV/
|
|
5
|
+
env/
|
|
6
|
+
|
|
7
|
+
# Byte-compiled / optimized files
|
|
8
|
+
__pycache__/
|
|
9
|
+
*.py[cod]
|
|
10
|
+
*$py.class
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
|
|
17
|
+
# Unit test / coverage
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
|
|
24
|
+
# Local databases & contracts
|
|
25
|
+
*.db
|
|
26
|
+
*.sqlite
|
|
27
|
+
*.sqlite3
|
|
28
|
+
.contracts.db
|
|
29
|
+
|
|
30
|
+
# IDE
|
|
31
|
+
.idea/
|
|
32
|
+
.vscode/
|
|
33
|
+
*.swp
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Agent Operating Guide
|
|
2
|
+
|
|
3
|
+
## Before changing code
|
|
4
|
+
|
|
5
|
+
Read, in this order:
|
|
6
|
+
|
|
7
|
+
1. `docs/spec.md`
|
|
8
|
+
2. `docs/architecture.md`
|
|
9
|
+
3. `docs/project-state.md`
|
|
10
|
+
4. relevant ADRs under `docs/adr/`
|
|
11
|
+
5. the current plan under `plans/active/`
|
|
12
|
+
6. existing tests for the behavior being changed
|
|
13
|
+
|
|
14
|
+
Do not rely on previous chat history as the authoritative source of project state.
|
|
15
|
+
|
|
16
|
+
## Core invariants
|
|
17
|
+
|
|
18
|
+
- Canonical domain models remain independent of dbt.
|
|
19
|
+
- Published contract versions are immutable.
|
|
20
|
+
- Compatibility decisions are deterministic and explainable.
|
|
21
|
+
- Unknown compatibility must not silently pass.
|
|
22
|
+
- Declared consumer expectations and observed lineage are distinct concepts.
|
|
23
|
+
- Provider-specific Azure DevOps types must not leak into core domain code.
|
|
24
|
+
- CLI, persistence, discovery, and domain logic remain separated.
|
|
25
|
+
- A producer PR must not require downstream repositories to be cloned.
|
|
26
|
+
- Secrets must never be persisted in the registry or written to logs.
|
|
27
|
+
|
|
28
|
+
## Development workflow
|
|
29
|
+
|
|
30
|
+
For each meaningful feature:
|
|
31
|
+
|
|
32
|
+
1. Read the relevant specification.
|
|
33
|
+
2. Create or update an implementation plan.
|
|
34
|
+
3. Define acceptance criteria.
|
|
35
|
+
4. Inspect existing tests.
|
|
36
|
+
5. Add or update tests describing expected behavior.
|
|
37
|
+
6. Implement the smallest complete vertical change.
|
|
38
|
+
7. Run all required checks.
|
|
39
|
+
8. Update documentation if public behavior changed.
|
|
40
|
+
9. Create an ADR if an architectural decision was introduced.
|
|
41
|
+
10. Update `docs/project-state.md`.
|
|
42
|
+
|
|
43
|
+
Do not perform unrelated refactoring during feature work.
|
|
44
|
+
|
|
45
|
+
## Definition of done
|
|
46
|
+
|
|
47
|
+
A task is complete only when:
|
|
48
|
+
|
|
49
|
+
- acceptance criteria are satisfied
|
|
50
|
+
- tests pass
|
|
51
|
+
- linting passes
|
|
52
|
+
- formatting passes
|
|
53
|
+
- type checking passes
|
|
54
|
+
- public CLI behavior is documented
|
|
55
|
+
- important error cases are tested
|
|
56
|
+
- architecture boundaries are preserved
|
|
57
|
+
- project state is updated
|
|
58
|
+
|
|
59
|
+
## Required validation
|
|
60
|
+
|
|
61
|
+
Before declaring work complete, run:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pytest
|
|
65
|
+
ruff check .
|
|
66
|
+
ruff format --check .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Also run the configured type checker (`mypy src tests`).
|
|
70
|
+
|
|
71
|
+
For changes affecting the CLI, execute the relevant command manually against a fixture or example.
|
|
72
|
+
|
|
73
|
+
## Implementation style
|
|
74
|
+
|
|
75
|
+
Prefer:
|
|
76
|
+
|
|
77
|
+
- small typed functions
|
|
78
|
+
- explicit domain objects
|
|
79
|
+
- Pydantic models at boundaries
|
|
80
|
+
- protocols for infrastructure abstractions
|
|
81
|
+
- deterministic behavior
|
|
82
|
+
- structured error types
|
|
83
|
+
- dependency injection where infrastructure needs substitution in tests
|
|
84
|
+
|
|
85
|
+
Avoid:
|
|
86
|
+
|
|
87
|
+
- global mutable state
|
|
88
|
+
- giant service classes
|
|
89
|
+
- untyped dictionaries passed through multiple layers
|
|
90
|
+
- provider-specific behavior in the domain
|
|
91
|
+
- hidden network access
|
|
92
|
+
- unnecessary framework abstractions
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Contributing to dbt_contracts
|
|
2
|
+
|
|
3
|
+
We welcome contributions to `dbt_contracts`!
|
|
4
|
+
|
|
5
|
+
## Architectural Guidelines
|
|
6
|
+
|
|
7
|
+
Before making changes, please review:
|
|
8
|
+
1. `AGENTS.md` - Core invariants, workflow, and definition of done.
|
|
9
|
+
2. `docs/architecture.md` - Architectural layers and dependency boundaries.
|
|
10
|
+
3. `docs/adr/` - Architecture Decision Records.
|
|
11
|
+
4. `plans/` - Active and backlog implementation plans.
|
|
12
|
+
|
|
13
|
+
## Development Setup
|
|
14
|
+
|
|
15
|
+
1. Create a Python 3.11+ virtual environment:
|
|
16
|
+
```bash
|
|
17
|
+
python -m venv .venv
|
|
18
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\Activate.ps1
|
|
19
|
+
```
|
|
20
|
+
2. Install package and dev dependencies:
|
|
21
|
+
```bash
|
|
22
|
+
pip install -e ".[dev]"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Validation
|
|
26
|
+
|
|
27
|
+
Before submitting a PR, ensure all checks pass:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pytest
|
|
31
|
+
ruff check .
|
|
32
|
+
ruff format --check .
|
|
33
|
+
mypy src tests
|
|
34
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrew Ferguson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: dbt-data-contracts
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A lightweight data contract control plane for multi-repository dbt ecosystems
|
|
5
|
+
Author: dbt_contracts contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: ci-cd,data-contracts,data-mesh,dbt,semver
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Requires-Dist: pydantic>=2.5.0
|
|
20
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
21
|
+
Requires-Dist: rich>=13.7.0
|
|
22
|
+
Requires-Dist: semver>=3.0.0
|
|
23
|
+
Requires-Dist: sqlalchemy>=2.0.0
|
|
24
|
+
Requires-Dist: typer>=0.12.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: types-pyyaml>=6.0.12; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# dbt_contracts
|
|
34
|
+
|
|
35
|
+
> A lightweight **data contract control plane** for multi-repository dbt ecosystems.
|
|
36
|
+
|
|
37
|
+
dbt model contracts validate what a model publishes internally, but in a multi-repository data-product ecosystem, producers also need to know whether proposed interface changes violate downstream consumer expectations without cloning or rebuilding downstream repositories in CI.
|
|
38
|
+
|
|
39
|
+
`dbt_contracts` provides:
|
|
40
|
+
|
|
41
|
+
- **Canonical Data Contracts**: Infrastructure-independent contract models with column schemas, types, nullability, and provenance.
|
|
42
|
+
- **dbt Artifact Ingestion**: Automatic extraction of public data models from dbt `manifest.json`.
|
|
43
|
+
- **Central Contract Registry**: SQLite-based (and extensible) registry storing immutable contract history and consumer declarations.
|
|
44
|
+
- **Explicit Consumer Expectations**: Downstream teams declare version ranges and required columns in simple YAML.
|
|
45
|
+
- **SemVer Compatibility Engine**: Deterministic classification of changes as `PATCH`, `MINOR`, `MAJOR`, or `UNKNOWN`.
|
|
46
|
+
- **Consumer Impact Analysis**: Identify which specific consumers and models will break when an interface changes.
|
|
47
|
+
- **CI PR Gates**: Producer CI runs `dbt-contracts check` with standardized exit codes (`0` = valid, `1` = breaking gate failure, `2` = error).
|
|
48
|
+
- **Organization-Scale Discovery**: Scan Azure DevOps organizations to discover dbt projects and consumer contracts without cloning.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Architecture
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
dbt artifacts / repository metadata
|
|
56
|
+
|
|
|
57
|
+
v
|
|
58
|
+
Discovery & Ingestion
|
|
59
|
+
|
|
|
60
|
+
v
|
|
61
|
+
Canonical Contract Model
|
|
62
|
+
|
|
|
63
|
+
+-------+---------+
|
|
64
|
+
| |
|
|
65
|
+
v v
|
|
66
|
+
Contract Registry Compatibility Engine
|
|
67
|
+
| |
|
|
68
|
+
+--------+--------+
|
|
69
|
+
|
|
|
70
|
+
v
|
|
71
|
+
Consumer Impact
|
|
72
|
+
|
|
|
73
|
+
v
|
|
74
|
+
CI Gate
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install dbt-data-contracts
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For development:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://github.com/your-org/dbt_contracts.git
|
|
89
|
+
cd dbt_contracts
|
|
90
|
+
python -m venv .venv
|
|
91
|
+
source .venv/bin/activate # Or .venv\Scripts\Activate.ps1 on Windows
|
|
92
|
+
pip install -e ".[dev]"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Quickstart & CLI Usage
|
|
98
|
+
|
|
99
|
+
### 1. Ingest contracts from a dbt manifest
|
|
100
|
+
|
|
101
|
+
Inspect public contracts discovered in a dbt manifest:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
dbt-contracts ingest --manifest target/manifest.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 2. Publish a contract version to the registry
|
|
108
|
+
|
|
109
|
+
Publish contracts for public dbt models (e.g. `1.0.0`):
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
dbt-contracts publish \
|
|
113
|
+
--manifest target/manifest.json \
|
|
114
|
+
--version 1.0.0 \
|
|
115
|
+
--registry .contracts.db
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. Register a downstream consumer expectation
|
|
119
|
+
|
|
120
|
+
Downstream consumers define `data-contract-consumers.yml`:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
consumer: finance
|
|
124
|
+
|
|
125
|
+
dependencies:
|
|
126
|
+
- product: orders
|
|
127
|
+
model: fct_orders
|
|
128
|
+
version: "^1.0.0"
|
|
129
|
+
expectations:
|
|
130
|
+
columns:
|
|
131
|
+
order_id:
|
|
132
|
+
data_type: bigint
|
|
133
|
+
required: true
|
|
134
|
+
amount:
|
|
135
|
+
data_type: numeric
|
|
136
|
+
required: true
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Register the expectation in the central registry:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
dbt-contracts consumer register \
|
|
143
|
+
--file data-contract-consumers.yml \
|
|
144
|
+
--registry .contracts.db
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 4. Check proposed changes in Producer CI
|
|
148
|
+
|
|
149
|
+
In producer pull request pipelines, test proposed contracts against published contracts and registered consumers:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
dbt-contracts check \
|
|
153
|
+
--manifest target/manifest.json \
|
|
154
|
+
--proposed-version 1.1.0 \
|
|
155
|
+
--registry .contracts.db
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If a breaking change is detected (e.g., removing `amount` while `finance` requires it), the command outputs a detailed impact report and exits with code `1`:
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
BREAKING CHANGE DETECTED: orders.fct_orders
|
|
162
|
+
|
|
163
|
+
Proposed: 1.1.0 (Current: 1.0.0)
|
|
164
|
+
Severity: MAJOR
|
|
165
|
+
|
|
166
|
+
Breaking changes:
|
|
167
|
+
- Column 'amount' was removed
|
|
168
|
+
|
|
169
|
+
Affected consumers:
|
|
170
|
+
- finance (expects 'amount: numeric', pinned to ^1.0.0)
|
|
171
|
+
|
|
172
|
+
SemVer Validation:
|
|
173
|
+
FAIL: Breaking changes require a MAJOR version bump (expected >= 2.0.0).
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
If the proposed version is updated to `2.0.0`:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
dbt-contracts check \
|
|
180
|
+
--manifest target/manifest.json \
|
|
181
|
+
--proposed-version 2.0.0 \
|
|
182
|
+
--registry .contracts.db
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The check passes with exit code `0`, confirming that `1.0.0` remains intact for existing consumers while `2.0.0` introduces the new breaking contract.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Development & Validation
|
|
190
|
+
|
|
191
|
+
Run all checks:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
pytest
|
|
195
|
+
ruff check .
|
|
196
|
+
ruff format --check .
|
|
197
|
+
mypy src tests
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Or run the dev check script:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
./scripts/dev-check.sh
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT License. See [LICENSE](LICENSE) for details.
|