Skip to content

feat: make hexagonal scaffolding optional via copier question#3

Open
mariushelf wants to merge 1 commit into
feat/hexagonal-architecturefrom
feat/optional-hexagonal
Open

feat: make hexagonal scaffolding optional via copier question#3
mariushelf wants to merge 1 commit into
feat/hexagonal-architecturefrom
feat/optional-hexagonal

Conversation

@mariushelf

Copy link
Copy Markdown
Owner

Stacked on #2 (base branch: feat/hexagonal-architecture). Review/merge #2 first; this PR's diff is only the "make it optional" delta.

What

Adds an include_hexagonal copier question (bool, default true). When false, the generated project is the original flat layout (main/settings/utils) with none of the hexagonal machinery — no layers, no example slice, no import-linter.

How it's gated (all at generation time)

Concern Mechanism
domain/ services/ adapters/ dirs + example test Jinja conditional path names — e.g. {% if include_hexagonal %}domain{% endif %}. Copier skips empty-named paths and their subtree.
import-linter dep + [tool.importlinter] contracts wrapped in {% if include_hexagonal %} in pyproject.toml.jinja
lint-imports pre-commit hook .pre-commit-config.yaml.jinja, hook wrapped
Makefile import_lint Makefile.jinja; target becomes a no-op @echo in flat mode (kept so CI's make import_lint stays valid), and dropped from the lint target's deps
AGENTS.md / README architecture docs conditional sections; AGENTS.md's lint note stops mentioning import-linter
CI workflow left untemplatedcicd.yaml is full of GitHub ${{ }} that clashes with Jinja's {{ }}. Its import-linter step calls make import_lint, which is the no-op in flat mode.

Verification

tests/test_template.py is now parametrised over include_hexagonal=[True, False], so each of the 6 checks runs against both a hexagonal and a flat generated project: renders the right files, pytest, python -m main, make lint, make test, and pre-commit run --all-files. All 12 pass locally.

test_template_renders additionally asserts the domain/ dir and example test exist iff include_hexagonal is true.

Add an `include_hexagonal` boolean question (default true). When false,
the generated project gets only the flat src layout (main/settings/utils)
and none of the hexagonal machinery.

The scaffolding is gated entirely at generation time:

- The domain/services/adapters directories and the example test use
  Jinja conditional names (`{% if include_hexagonal %}...{% endif %}`),
  so copier skips them when the answer is false.
- pyproject.toml.jinja wraps the import-linter dev dependency and the
  `[tool.importlinter]` contracts in the same conditional.
- AGENTS.md.jinja and README.md.jinja drop their Architecture sections,
  and AGENTS.md's lint note no longer mentions import-linter.
- .pre-commit-config.yaml and Makefile become .jinja templates: the
  lint-imports pre-commit hook is omitted, and the Makefile's
  `import_lint` target becomes a no-op (kept so CI's `make import_lint`
  step stays valid in both modes). cicd.yaml is left untemplated to
  avoid clashing with GitHub's `${{ }}` expressions.

The template's test suite is now parametrised over both answers, so the
hexagonal and flat layouts are each generated and verified end to end
(lint, test, main, pre-commit).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant