dbt-arch-unit 0.1.1__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_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +36 -0
- dbt_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/config.yml +8 -0
- dbt_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
- dbt_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/new_rule.yml +62 -0
- dbt_arch_unit-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +19 -0
- dbt_arch_unit-0.1.1/.github/dependabot.yml +13 -0
- dbt_arch_unit-0.1.1/.github/workflows/ci.yml +44 -0
- dbt_arch_unit-0.1.1/.github/workflows/release.yml +54 -0
- dbt_arch_unit-0.1.1/.gitignore +34 -0
- dbt_arch_unit-0.1.1/.pre-commit-config.yaml +18 -0
- dbt_arch_unit-0.1.1/.pre-commit-hooks.yaml +7 -0
- dbt_arch_unit-0.1.1/CHANGELOG.md +45 -0
- dbt_arch_unit-0.1.1/CODE_OF_CONDUCT.md +59 -0
- dbt_arch_unit-0.1.1/CONTRIBUTING.md +116 -0
- dbt_arch_unit-0.1.1/LICENSE +21 -0
- dbt_arch_unit-0.1.1/PKG-INFO +170 -0
- dbt_arch_unit-0.1.1/README.md +136 -0
- dbt_arch_unit-0.1.1/SECURITY.md +30 -0
- dbt_arch_unit-0.1.1/pyproject.toml +90 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/__init__.py +3 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/cli.py +242 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/config.py +85 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/context.py +187 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/html_report.py +229 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/models/__init__.py +1 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/models/manifest.py +150 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/__init__.py +1 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/manifest_parser.py +24 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/project_parser.py +25 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/sql_parser.py +145 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/py.typed +0 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/reporting.py +56 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/__init__.py +70 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/dependencies.py +241 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/documentation.py +80 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/materialization.py +89 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/naming.py +120 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/style.py +129 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/testing.py +100 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/runner.py +59 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/scaffold.py +224 -0
- dbt_arch_unit-0.1.1/src/dbt_arch_unit/violation.py +31 -0
- dbt_arch_unit-0.1.1/tests/conftest.py +30 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/dbt_arch_unit.yaml +33 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/dbt_project.yml +4 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/marts/dim_customers.sql +9 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/marts/fct_orders.sql +10 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/marts/orders_summary.sql +1 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/reporting/rpt_revenue.sql +1 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/staging/stg_customers.sql +13 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/staging/stg_orders.sql +5 -0
- dbt_arch_unit-0.1.1/tests/fixtures/demo_project/target/manifest.json +200 -0
- dbt_arch_unit-0.1.1/tests/test_cli.py +65 -0
- dbt_arch_unit-0.1.1/tests/test_dependencies.py +35 -0
- dbt_arch_unit-0.1.1/tests/test_documentation.py +22 -0
- dbt_arch_unit-0.1.1/tests/test_html_report.py +76 -0
- dbt_arch_unit-0.1.1/tests/test_materialization.py +26 -0
- dbt_arch_unit-0.1.1/tests/test_naming.py +21 -0
- dbt_arch_unit-0.1.1/tests/test_scaffold.py +44 -0
- dbt_arch_unit-0.1.1/tests/test_sql_parser.py +44 -0
- dbt_arch_unit-0.1.1/tests/test_style.py +25 -0
- dbt_arch_unit-0.1.1/tests/test_testing.py +32 -0
- dbt_arch_unit-0.1.1/uv.lock +554 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: 🐛 Bug report
|
|
2
|
+
description: Something isn't working as expected
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: Thanks for taking the time to file a bug report!
|
|
8
|
+
- type: textarea
|
|
9
|
+
id: what-happened
|
|
10
|
+
attributes:
|
|
11
|
+
label: What happened?
|
|
12
|
+
description: A clear description of the bug and what you expected instead.
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: repro
|
|
17
|
+
attributes:
|
|
18
|
+
label: Steps to reproduce
|
|
19
|
+
description: Commands run, relevant `dbt_arch_unit.yaml` snippet, and any model SQL.
|
|
20
|
+
render: shell
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
- type: input
|
|
24
|
+
id: version
|
|
25
|
+
attributes:
|
|
26
|
+
label: dbt-arch-unit version
|
|
27
|
+
description: Output of `dbt-arch-unit version`.
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
- type: input
|
|
31
|
+
id: env
|
|
32
|
+
attributes:
|
|
33
|
+
label: Python / dbt version & OS
|
|
34
|
+
placeholder: "Python 3.13, dbt 1.8, macOS 15"
|
|
35
|
+
validations:
|
|
36
|
+
required: false
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: 💬 Questions & discussions
|
|
4
|
+
url: https://github.com/dardanxh/dbt-arch-unit/discussions
|
|
5
|
+
about: Ask questions, share setups, and discuss ideas here.
|
|
6
|
+
- name: 📖 Documentation
|
|
7
|
+
url: https://github.com/dardanxh/dbt-arch-unit#readme
|
|
8
|
+
about: Read the README and rule catalog first.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: ✨ Feature request
|
|
2
|
+
description: Suggest an enhancement (not a new rule — use the rule proposal template for that)
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: What problem does this solve?
|
|
9
|
+
description: The use case or pain point motivating the request.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution
|
|
16
|
+
description: What you'd like to see happen. Include CLI/config examples if relevant.
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: Alternatives considered
|
|
23
|
+
validations:
|
|
24
|
+
required: false
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: 📐 New rule proposal
|
|
2
|
+
description: Propose a new architecture/convention rule for dbt projects
|
|
3
|
+
labels: ["rule-proposal"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Rules are small functions that check a dbt project against a convention.
|
|
9
|
+
See CONTRIBUTING.md for how they're implemented.
|
|
10
|
+
- type: input
|
|
11
|
+
id: name
|
|
12
|
+
attributes:
|
|
13
|
+
label: Proposed rule name
|
|
14
|
+
placeholder: "e.g. max-macro-depth"
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
- type: textarea
|
|
18
|
+
id: enforces
|
|
19
|
+
attributes:
|
|
20
|
+
label: What does it enforce?
|
|
21
|
+
description: The convention/best practice and why it matters.
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
- type: dropdown
|
|
25
|
+
id: source
|
|
26
|
+
attributes:
|
|
27
|
+
label: Data source
|
|
28
|
+
description: Where the check gets its information.
|
|
29
|
+
options:
|
|
30
|
+
- manifest (manifest.json)
|
|
31
|
+
- file (raw .sql/.yml)
|
|
32
|
+
- both
|
|
33
|
+
validations:
|
|
34
|
+
required: true
|
|
35
|
+
- type: dropdown
|
|
36
|
+
id: category
|
|
37
|
+
attributes:
|
|
38
|
+
label: Category
|
|
39
|
+
options:
|
|
40
|
+
- dependencies
|
|
41
|
+
- naming
|
|
42
|
+
- testing
|
|
43
|
+
- documentation
|
|
44
|
+
- style
|
|
45
|
+
- materialization
|
|
46
|
+
validations:
|
|
47
|
+
required: true
|
|
48
|
+
- type: textarea
|
|
49
|
+
id: config
|
|
50
|
+
attributes:
|
|
51
|
+
label: Configuration options
|
|
52
|
+
description: Any `config:` keys the rule should accept (name + default).
|
|
53
|
+
placeholder: "max: maximum allowed value (default: 5)"
|
|
54
|
+
validations:
|
|
55
|
+
required: false
|
|
56
|
+
- type: textarea
|
|
57
|
+
id: example
|
|
58
|
+
attributes:
|
|
59
|
+
label: Example that should fail
|
|
60
|
+
render: sql
|
|
61
|
+
validations:
|
|
62
|
+
required: false
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do and why? -->
|
|
4
|
+
|
|
5
|
+
## Related issue
|
|
6
|
+
|
|
7
|
+
<!-- e.g. Closes #123 -->
|
|
8
|
+
|
|
9
|
+
## Changes
|
|
10
|
+
|
|
11
|
+
<!-- Bullet the key changes. If you added/changed a rule, name it. -->
|
|
12
|
+
|
|
13
|
+
## Checklist
|
|
14
|
+
|
|
15
|
+
- [ ] `uv run ruff check` and `uv run ruff format --check` pass
|
|
16
|
+
- [ ] `uv run mypy src` passes
|
|
17
|
+
- [ ] `uv run pytest` passes
|
|
18
|
+
- [ ] Added/updated tests (with a fixture case if a new rule)
|
|
19
|
+
- [ ] Updated `README.md` / `CHANGELOG.md` if behaviour or the rule catalog changed
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "github-actions"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
labels: ["dependencies", "ci"]
|
|
8
|
+
|
|
9
|
+
- package-ecosystem: "pip"
|
|
10
|
+
directory: "/"
|
|
11
|
+
schedule:
|
|
12
|
+
interval: "weekly"
|
|
13
|
+
labels: ["dependencies"]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ci-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.13"]
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v6
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
|
|
28
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
29
|
+
run: uv python install ${{ matrix.python-version }}
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: uv sync --extra dev --python ${{ matrix.python-version }}
|
|
33
|
+
|
|
34
|
+
- name: Lint (ruff)
|
|
35
|
+
run: uv run ruff check
|
|
36
|
+
|
|
37
|
+
- name: Format check (ruff)
|
|
38
|
+
run: uv run ruff format --check
|
|
39
|
+
|
|
40
|
+
- name: Type check (mypy)
|
|
41
|
+
run: uv run mypy src
|
|
42
|
+
|
|
43
|
+
- name: Tests (pytest)
|
|
44
|
+
run: uv run pytest
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Automated versioning + releases via python-semantic-release.
|
|
4
|
+
# On every push to main it inspects Conventional Commits since the last tag and,
|
|
5
|
+
# if there is a releasable change (feat/fix/perf/BREAKING CHANGE), bumps the
|
|
6
|
+
# version, updates CHANGELOG.md, commits, tags vX.Y.Z, and creates a GitHub
|
|
7
|
+
# Release. PyPI publishing is gated on the PYPI_PUBLISH repo variable so it stays
|
|
8
|
+
# inert until you register a PyPI Trusted Publisher and set PYPI_PUBLISH=true.
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
branches: [main]
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: release
|
|
16
|
+
cancel-in-progress: false
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
release:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: write # push the release commit + tag, create the GitHub Release
|
|
23
|
+
outputs:
|
|
24
|
+
released: ${{ steps.release.outputs.released }}
|
|
25
|
+
tag: ${{ steps.release.outputs.tag }}
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
31
|
+
|
|
32
|
+
- name: Python Semantic Release
|
|
33
|
+
id: release
|
|
34
|
+
uses: python-semantic-release/python-semantic-release@v9
|
|
35
|
+
with:
|
|
36
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
37
|
+
|
|
38
|
+
publish:
|
|
39
|
+
needs: release
|
|
40
|
+
if: needs.release.outputs.released == 'true' && vars.PYPI_PUBLISH == 'true'
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
environment: pypi
|
|
43
|
+
permissions:
|
|
44
|
+
id-token: write # PyPI Trusted Publishing (OIDC)
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@v4
|
|
47
|
+
with:
|
|
48
|
+
ref: ${{ needs.release.outputs.tag }}
|
|
49
|
+
- name: Install uv
|
|
50
|
+
uses: astral-sh/setup-uv@v6
|
|
51
|
+
- name: Build
|
|
52
|
+
run: uv build
|
|
53
|
+
- name: Publish to PyPI
|
|
54
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
*.so
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
|
|
15
|
+
# Tooling caches
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
.coverage.*
|
|
21
|
+
htmlcov/
|
|
22
|
+
.tox/
|
|
23
|
+
|
|
24
|
+
# Editors / OS
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
*.swp
|
|
28
|
+
.DS_Store
|
|
29
|
+
|
|
30
|
+
# dbt-arch-unit generated artifacts
|
|
31
|
+
*_report.html
|
|
32
|
+
dbt_arch_unit_report.html
|
|
33
|
+
|
|
34
|
+
# Keep uv.lock tracked (it is the tool lockfile) — do NOT ignore it.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Local dev hooks for contributors. Install with: uv run pre-commit install
|
|
2
|
+
# (This is separate from `.pre-commit-hooks.yaml`, which exposes dbt-arch-unit
|
|
3
|
+
# as a hook for *downstream* dbt projects to consume.)
|
|
4
|
+
repos:
|
|
5
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
6
|
+
rev: v5.0.0
|
|
7
|
+
hooks:
|
|
8
|
+
- id: trailing-whitespace
|
|
9
|
+
- id: end-of-file-fixer
|
|
10
|
+
- id: check-yaml
|
|
11
|
+
- id: check-added-large-files
|
|
12
|
+
|
|
13
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
+
rev: v0.16.4
|
|
15
|
+
hooks:
|
|
16
|
+
- id: ruff
|
|
17
|
+
args: [--fix]
|
|
18
|
+
- id: ruff-format
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. This file is generated
|
|
4
|
+
automatically by [python-semantic-release](https://python-semantic-release.readthedocs.io)
|
|
5
|
+
from [Conventional Commits](https://www.conventionalcommits.org) — do not edit by hand.
|
|
6
|
+
|
|
7
|
+
<!-- version list -->
|
|
8
|
+
|
|
9
|
+
## v0.1.1 (2026-08-23)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- Ship py.typed marker for PEP 561 type support
|
|
14
|
+
([`6d9635d`](https://github.com/dardanxh/dbt-arch-unit/commit/6d9635dba8d9cb7885e33f54de1072b5bd5e3ae5))
|
|
15
|
+
|
|
16
|
+
The package declares "Typing :: Typed" but shipped no py.typed marker, so downstream type checkers
|
|
17
|
+
ignored dbt-arch-unit's inline types. Add the marker so consumers pick up the annotations.
|
|
18
|
+
|
|
19
|
+
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## v0.1.0 (2026-08-23)
|
|
23
|
+
|
|
24
|
+
### Continuous Integration
|
|
25
|
+
|
|
26
|
+
- Automate versioning and releases with python-semantic-release
|
|
27
|
+
([`9900087`](https://github.com/dardanxh/dbt-arch-unit/commit/9900087e648e40850b7f48e41a5fc5c8296f8ad1))
|
|
28
|
+
|
|
29
|
+
Version, git tag, GitHub Release and CHANGELOG are now derived from Conventional Commit messages.
|
|
30
|
+
The release workflow runs PSR on pushes to main; PyPI publishing is gated behind the PYPI_PUBLISH
|
|
31
|
+
repo variable.
|
|
32
|
+
|
|
33
|
+
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
34
|
+
|
|
35
|
+
### Features
|
|
36
|
+
|
|
37
|
+
- Dbt-arch-unit — architectural unit testing for dbt
|
|
38
|
+
([`9407556`](https://github.com/dardanxh/dbt-arch-unit/commit/9407556e51dad87e50c12add5f43e0a5e2c6582a))
|
|
39
|
+
|
|
40
|
+
Enforce a team's dbt conventions (layering, naming, testing, docs, style, materialization) via a
|
|
41
|
+
declarative dbt_arch_unit.yaml. Ships 38 rules, a Typer+Rich CLI
|
|
42
|
+
(check/report/list-rules/explain/init), a self-contained HTML report, and a pre-commit hook.
|
|
43
|
+
Includes CI, release automation, and full OSS governance files.
|
|
44
|
+
|
|
45
|
+
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment include:
|
|
18
|
+
|
|
19
|
+
- Demonstrating empathy and kindness toward other people
|
|
20
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
21
|
+
- Giving and gracefully accepting constructive feedback
|
|
22
|
+
- Accepting responsibility and apologizing to those affected by our mistakes
|
|
23
|
+
- Focusing on what is best for the overall community
|
|
24
|
+
|
|
25
|
+
Examples of unacceptable behavior include:
|
|
26
|
+
|
|
27
|
+
- The use of sexualized language or imagery, and sexual attention or advances
|
|
28
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
29
|
+
- Public or private harassment
|
|
30
|
+
- Publishing others' private information without explicit permission
|
|
31
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
32
|
+
professional setting
|
|
33
|
+
|
|
34
|
+
## Enforcement Responsibilities
|
|
35
|
+
|
|
36
|
+
Community leaders are responsible for clarifying and enforcing our standards and
|
|
37
|
+
will take appropriate and fair corrective action in response to any behavior
|
|
38
|
+
that they deem inappropriate, threatening, offensive, or harmful.
|
|
39
|
+
|
|
40
|
+
## Scope
|
|
41
|
+
|
|
42
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
43
|
+
an individual is officially representing the community in public spaces.
|
|
44
|
+
|
|
45
|
+
## Enforcement
|
|
46
|
+
|
|
47
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
48
|
+
reported to the community leaders responsible for enforcement at
|
|
49
|
+
**dardanxhymshiti@gmail.com**. All complaints will be reviewed and investigated
|
|
50
|
+
promptly and fairly. All community leaders are obligated to respect the privacy
|
|
51
|
+
and security of the reporter of any incident.
|
|
52
|
+
|
|
53
|
+
## Attribution
|
|
54
|
+
|
|
55
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
56
|
+
version 2.1, available at
|
|
57
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
|
58
|
+
|
|
59
|
+
[homepage]: https://www.contributor-covenant.org
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Contributing to dbt-arch-unit
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in improving **dbt-arch-unit**! This project turns a
|
|
4
|
+
team's dbt conventions into enforceable, testable rules. Contributions — new
|
|
5
|
+
rules, bug fixes, docs — are very welcome.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
You need [uv](https://docs.astral.sh/uv/) and Python 3.13+.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/dardanxh/dbt-arch-unit
|
|
13
|
+
cd dbt-arch-unit
|
|
14
|
+
uv sync --extra dev # install the package + dev tools
|
|
15
|
+
uv run dbt-arch-unit --help # sanity check
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## The checks CI runs (run them before opening a PR)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv run ruff check # lint
|
|
22
|
+
uv run ruff format --check # formatting
|
|
23
|
+
uv run mypy src # static types (strict)
|
|
24
|
+
uv run pytest # tests
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Optionally install the local git hooks so these run automatically:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv run pre-commit install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## How the project is organised
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
src/dbt_arch_unit/
|
|
37
|
+
models/manifest.py # typed view of dbt's manifest.json
|
|
38
|
+
parsers/ # manifest loader + raw-SQL fact extraction
|
|
39
|
+
config.py # the dbt_arch_unit.yaml contract (pydantic)
|
|
40
|
+
context.py # ProjectContext: layers, selectors, cached SQL, test indexes
|
|
41
|
+
rules/ # one module per category, one function per rule
|
|
42
|
+
runner.py reporting.py html_report.py cli.py scaffold.py
|
|
43
|
+
tests/ # per-category tests + a demo project fixture
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Adding a new rule
|
|
47
|
+
|
|
48
|
+
Rules are small, self-contained functions registered by name. To add one:
|
|
49
|
+
|
|
50
|
+
1. **Write the function** in the right category module under `src/dbt_arch_unit/rules/`
|
|
51
|
+
(`dependencies`, `naming`, `testing`, `documentation`, `style`, `materialization`).
|
|
52
|
+
Use the `@register(...)` decorator and the `(ctx, rule)` signature:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
@register(
|
|
56
|
+
"no-select-star",
|
|
57
|
+
"style",
|
|
58
|
+
"Models must not use `select *` in their final projection.",
|
|
59
|
+
source="file", # "manifest" | "file" | "both"
|
|
60
|
+
config_keys={"allow_in_ctes": "permit `select *` inside CTEs (default: true)"},
|
|
61
|
+
)
|
|
62
|
+
def no_select_star(ctx: ProjectContext, rule: RuleConfig) -> Iterable[Violation]:
|
|
63
|
+
for model in ctx.models_for(rule): # scoping is handled for you
|
|
64
|
+
if ctx.sql(model).has_select_star(allow_in_ctes=rule.config.get("allow_in_ctes", True)):
|
|
65
|
+
yield ctx.violation(rule, model, "uses `select *`")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Let `ctx.models_for(rule)` do the include/exclude/layer/tag scoping — never
|
|
69
|
+
re-implement it. Read manifest facts from `ctx`, and raw-SQL facts from
|
|
70
|
+
`ctx.sql(model)`.
|
|
71
|
+
|
|
72
|
+
2. **Add a fixture case** if needed in `tests/fixtures/demo_project/` (the demo
|
|
73
|
+
project is deliberately "bad" so rules have something to catch).
|
|
74
|
+
|
|
75
|
+
3. **Add a test** in the matching `tests/test_<category>.py` asserting exactly
|
|
76
|
+
which nodes the rule flags.
|
|
77
|
+
|
|
78
|
+
4. **Document it** — it shows up automatically in `dbt-arch-unit list-rules` and
|
|
79
|
+
`explain <rule>` from the `@register` metadata. Add it to `CHANGELOG.md`.
|
|
80
|
+
|
|
81
|
+
## Commit & PR conventions
|
|
82
|
+
|
|
83
|
+
- Keep PRs focused; one rule or fix per PR where possible.
|
|
84
|
+
- Ensure `ruff`, `mypy`, and `pytest` all pass.
|
|
85
|
+
- Update `README.md` when behaviour or the rule catalog changes. **Do not** edit
|
|
86
|
+
`CHANGELOG.md` — it is generated automatically (see below).
|
|
87
|
+
|
|
88
|
+
### Commit messages drive releases
|
|
89
|
+
|
|
90
|
+
This project uses [Conventional Commits](https://www.conventionalcommits.org)
|
|
91
|
+
and [python-semantic-release](https://python-semantic-release.readthedocs.io).
|
|
92
|
+
The commit type on `main` determines the next version and changelog entry — so
|
|
93
|
+
**your commit message matters**:
|
|
94
|
+
|
|
95
|
+
| Commit type | Release effect |
|
|
96
|
+
| ------------------------------------ | ------------------------- |
|
|
97
|
+
| `fix: …` | patch (0.1.0 → 0.1.1) |
|
|
98
|
+
| `feat: …` | minor (0.1.0 → 0.2.0) |
|
|
99
|
+
| `feat!: …` or a `BREAKING CHANGE:` footer | major (0.1.0 → 1.0.0) |
|
|
100
|
+
| `docs:` `chore:` `ci:` `refactor:` `test:` | no release |
|
|
101
|
+
|
|
102
|
+
On merge to `main`, the release workflow bumps the version in `pyproject.toml`
|
|
103
|
+
and `src/dbt_arch_unit/__init__.py`, updates `CHANGELOG.md`, tags `vX.Y.Z`, and
|
|
104
|
+
publishes a GitHub Release automatically. You can preview what would happen with:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
uvx python-semantic-release version --print # prints the next version, no changes
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Reporting bugs / proposing rules
|
|
111
|
+
|
|
112
|
+
Open an issue using the templates — there's a dedicated **"New rule proposal"**
|
|
113
|
+
template for suggesting architecture rules.
|
|
114
|
+
|
|
115
|
+
By contributing you agree that your contributions are licensed under the
|
|
116
|
+
project's [MIT License](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dardan Xhymshiti
|
|
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.
|