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.
Files changed (63) hide show
  1. dbt_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +36 -0
  2. dbt_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. dbt_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
  4. dbt_arch_unit-0.1.1/.github/ISSUE_TEMPLATE/new_rule.yml +62 -0
  5. dbt_arch_unit-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +19 -0
  6. dbt_arch_unit-0.1.1/.github/dependabot.yml +13 -0
  7. dbt_arch_unit-0.1.1/.github/workflows/ci.yml +44 -0
  8. dbt_arch_unit-0.1.1/.github/workflows/release.yml +54 -0
  9. dbt_arch_unit-0.1.1/.gitignore +34 -0
  10. dbt_arch_unit-0.1.1/.pre-commit-config.yaml +18 -0
  11. dbt_arch_unit-0.1.1/.pre-commit-hooks.yaml +7 -0
  12. dbt_arch_unit-0.1.1/CHANGELOG.md +45 -0
  13. dbt_arch_unit-0.1.1/CODE_OF_CONDUCT.md +59 -0
  14. dbt_arch_unit-0.1.1/CONTRIBUTING.md +116 -0
  15. dbt_arch_unit-0.1.1/LICENSE +21 -0
  16. dbt_arch_unit-0.1.1/PKG-INFO +170 -0
  17. dbt_arch_unit-0.1.1/README.md +136 -0
  18. dbt_arch_unit-0.1.1/SECURITY.md +30 -0
  19. dbt_arch_unit-0.1.1/pyproject.toml +90 -0
  20. dbt_arch_unit-0.1.1/src/dbt_arch_unit/__init__.py +3 -0
  21. dbt_arch_unit-0.1.1/src/dbt_arch_unit/cli.py +242 -0
  22. dbt_arch_unit-0.1.1/src/dbt_arch_unit/config.py +85 -0
  23. dbt_arch_unit-0.1.1/src/dbt_arch_unit/context.py +187 -0
  24. dbt_arch_unit-0.1.1/src/dbt_arch_unit/html_report.py +229 -0
  25. dbt_arch_unit-0.1.1/src/dbt_arch_unit/models/__init__.py +1 -0
  26. dbt_arch_unit-0.1.1/src/dbt_arch_unit/models/manifest.py +150 -0
  27. dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/__init__.py +1 -0
  28. dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/manifest_parser.py +24 -0
  29. dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/project_parser.py +25 -0
  30. dbt_arch_unit-0.1.1/src/dbt_arch_unit/parsers/sql_parser.py +145 -0
  31. dbt_arch_unit-0.1.1/src/dbt_arch_unit/py.typed +0 -0
  32. dbt_arch_unit-0.1.1/src/dbt_arch_unit/reporting.py +56 -0
  33. dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/__init__.py +70 -0
  34. dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/dependencies.py +241 -0
  35. dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/documentation.py +80 -0
  36. dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/materialization.py +89 -0
  37. dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/naming.py +120 -0
  38. dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/style.py +129 -0
  39. dbt_arch_unit-0.1.1/src/dbt_arch_unit/rules/testing.py +100 -0
  40. dbt_arch_unit-0.1.1/src/dbt_arch_unit/runner.py +59 -0
  41. dbt_arch_unit-0.1.1/src/dbt_arch_unit/scaffold.py +224 -0
  42. dbt_arch_unit-0.1.1/src/dbt_arch_unit/violation.py +31 -0
  43. dbt_arch_unit-0.1.1/tests/conftest.py +30 -0
  44. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/dbt_arch_unit.yaml +33 -0
  45. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/dbt_project.yml +4 -0
  46. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/marts/dim_customers.sql +9 -0
  47. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/marts/fct_orders.sql +10 -0
  48. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/marts/orders_summary.sql +1 -0
  49. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/reporting/rpt_revenue.sql +1 -0
  50. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/staging/stg_customers.sql +13 -0
  51. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/models/staging/stg_orders.sql +5 -0
  52. dbt_arch_unit-0.1.1/tests/fixtures/demo_project/target/manifest.json +200 -0
  53. dbt_arch_unit-0.1.1/tests/test_cli.py +65 -0
  54. dbt_arch_unit-0.1.1/tests/test_dependencies.py +35 -0
  55. dbt_arch_unit-0.1.1/tests/test_documentation.py +22 -0
  56. dbt_arch_unit-0.1.1/tests/test_html_report.py +76 -0
  57. dbt_arch_unit-0.1.1/tests/test_materialization.py +26 -0
  58. dbt_arch_unit-0.1.1/tests/test_naming.py +21 -0
  59. dbt_arch_unit-0.1.1/tests/test_scaffold.py +44 -0
  60. dbt_arch_unit-0.1.1/tests/test_sql_parser.py +44 -0
  61. dbt_arch_unit-0.1.1/tests/test_style.py +25 -0
  62. dbt_arch_unit-0.1.1/tests/test_testing.py +32 -0
  63. 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,7 @@
1
+ - id: dbt-arch-unit
2
+ name: dbt architecture unit tests
3
+ description: Enforce dbt architecture rules declared in dbt_arch_unit.yaml
4
+ entry: dbt-arch-unit check
5
+ language: python
6
+ pass_filenames: false
7
+ always_run: true
@@ -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.