Skip to content

Commit b55021b

Browse files
authored
Merge pull request #3 from mariushelf/feat/optional-hexagonal
feat: make hexagonal scaffolding optional via copier question
2 parents 82456d1 + 728a521 commit b55021b

17 files changed

Lines changed: 73 additions & 38 deletions

File tree

‎copier.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,11 @@ license:
7171
- GPL-3.0-or-later
7272
- LicenseRef-Proprietary
7373
default: MIT
74+
75+
include_hexagonal:
76+
type: bool
77+
help: >-
78+
Scaffold a hexagonal (ports-and-adapters) architecture? Adds domain/services/
79+
adapters layers with an example slice, plus import-linter contracts that
80+
enforce the layer boundaries.
81+
default: true

‎template/.github/workflows/cicd.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: ty
3333
run: make ty
3434
- name: import-linter
35-
run: uv run --no-sources lint-imports
35+
run: make import_lint
3636
test:
3737
runs-on: ubuntu-latest
3838
strategy:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ repos:
2222
language: system
2323
files: ^src/.*\.py$
2424
exclude: ^src/legacy/.*\.py$
25+
{%- if include_hexagonal %}
2526
- id: lint_imports
2627
name: lint imports
2728
entry: uv run lint-imports
2829
language: system
2930
pass_filenames: false
31+
{%- endif %}

‎template/AGENTS.md.jinja‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Use semantic commit messages:
2020
- `chore:` maintenance tasks, dependency updates, CI config, cleanup of things that work but are unnecessary
2121

2222
Do NOT add "Co-Authored-By" or any AI attribution trailers to commit messages.
23-
23+
{% if include_hexagonal %}
2424
## Architecture
2525

2626
This project follows a hexagonal (ports-and-adapters) architecture. The
@@ -60,9 +60,13 @@ The `domain`, `services`, and `adapters` packages ship with a small,
6060
clearly-marked example slice (a `Note` entity, a `NoteRepository` port, an
6161
in-memory adapter, and a `NoteService`). Search for `# --- example` and delete
6262
those blocks once you start modelling your own domain.
63-
63+
{% endif %}
6464
## Testing & Linting
6565

6666
- `make test` runs the test suite.
67+
{%- if include_hexagonal %}
6768
- `make lint` runs ruff, the `ty` type checker, and the `import-linter`
6869
architecture contracts.
70+
{%- else %}
71+
- `make lint` runs ruff and the `ty` type checker.
72+
{%- endif %}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ ruff:
3333
uv run --no-sources ruff check --fix --exit-non-zero-on-fix src tests
3434

3535
import_lint:
36+
{%- if include_hexagonal %}
3637
uv run --no-sources lint-imports
38+
{%- else %}
39+
@echo "import-linter is not configured (no hexagonal scaffolding)."
40+
{%- endif %}
3741

3842
type_check: ty
3943

40-
lint: ruff type_check import_lint
44+
lint: ruff type_check{% if include_hexagonal %} import_lint{% endif %}
4145

4246
pre_commit:
4347
pre-commit run --all-files

‎template/README.md.jinja‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
Original repository: [https://github.com/{{ github_username }}/{{ project_slug }}](https://github.com/{{ github_username }}/{{ project_slug }})
1010

11+
{% if include_hexagonal -%}
1112

1213
# Architecture
1314

@@ -16,6 +17,7 @@ organised into `domain`, `services`, and `adapters` layers. The layer
1617
boundaries are enforced by [import-linter](https://import-linter.readthedocs.io/);
1718
run `make lint` to check them. See [`AGENTS.md`](AGENTS.md) for the full rules.
1819

20+
{% endif -%}
1921

2022
# Installation
2123

‎template/pyproject.toml.jinja‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ type = "github"
9494

9595
[dependency-groups]
9696
dev = [
97+
{%- if include_hexagonal %}
9798
"import-linter>=2.0",
99+
{%- endif %}
98100
"pytest>=8.0",
99101
"ruff>=0.15",
100102
"ty>=0.0.17",
@@ -107,6 +109,7 @@ docs = [
107109
"pydata-sphinx-theme>=0.17.1",
108110
]
109111

112+
{% if include_hexagonal %}
110113
[tool.importlinter]
111114
root_packages = ["{{ project_slug }}"]
112115
include_external_packages = true
@@ -150,3 +153,4 @@ forbidden_modules = [
150153
"requests",
151154
"sqlalchemy",
152155
]
156+
{% endif %}

template/src/{{ project_slug }}/adapters/__init__.py.jinja renamed to template/src/{{ project_slug }}/{% if include_hexagonal %}adapters{% endif %}/__init__.py.jinja

File renamed without changes.

template/src/{{ project_slug }}/adapters/in_memory_note_repository.py.jinja renamed to template/src/{{ project_slug }}/{% if include_hexagonal %}adapters{% endif %}/in_memory_note_repository.py.jinja

File renamed without changes.

template/src/{{ project_slug }}/domain/__init__.py.jinja renamed to template/src/{{ project_slug }}/{% if include_hexagonal %}domain{% endif %}/__init__.py.jinja

File renamed without changes.

0 commit comments

Comments
 (0)