diff --git a/README.md b/README.md index a3e0fb5..47ec118 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # infra -Copier template for the root of a project: `docker-compose.yml` that includes every part, a `Makefile` that drives compose and delegates `fmt`, `check` and `build` to parts, `.env.example`, `.gitignore`, `CLAUDE.md` and pre-commit hooks. +Copier template for the root of a project. With `layout: parts` it ships a `docker-compose.yml` that includes every part, a `Makefile` that drives compose and delegates `fmt`, `check` and `build` to parts, and an `.env.example` whose `COMPOSE_FILE` adds each part's `docker-compose.local.yml`. With `layout: single` a part template renders straight into the root and infra ships only `.gitignore`, `CLAUDE.md` and pre-commit hooks. A part is a directory with: -- `docker-compose.yml` with root-relative paths, plus `docker-compose.local.yml` and `docker-compose.prod.yml` selected by `COMPOSE_ENV` +- `docker-compose.yml` with root-relative paths, plus `docker-compose.local.yml` and `docker-compose.prod.yml` picked through `COMPOSE_FILE` in the root `.env` - `Makefile` with `fmt`, `check` and `build` targets - `.env.example` appended to the root `.env` by `make env` - `CLAUDE.md` with the part's checking commands @@ -12,6 +12,6 @@ A part is a directory with: Application services carry the `services` profile, databases and other infrastructure carry `external`. ```sh -copier copy --trust -d 'parts=["backend","frontend"]' +copier copy --trust -d layout=parts -d 'parts=["backend","frontend"]' copier update -a .copier/infra.yml ``` diff --git a/copier.yml b/copier.yml index 0a9ac7d..958fb6d 100644 --- a/copier.yml +++ b/copier.yml @@ -4,9 +4,18 @@ _answers_file: .copier/infra.yml _envops: keep_trailing_newline: true +layout: + type: str + help: Where the code lives + choices: + Parts in their own directories: parts + A single part at the root: single + default: parts + parts: type: str multiselect: true + when: "{{ layout == 'parts' }}" help: Parts that live in their own directory with a docker-compose.yml and a Makefile choices: backend: backend diff --git a/template/.env.example b/template/.env.example deleted file mode 100644 index 2bcba39..0000000 --- a/template/.env.example +++ /dev/null @@ -1 +0,0 @@ -COMPOSE_ENV=local diff --git a/template/.gitignore b/template/.gitignore deleted file mode 100644 index 817009b..0000000 --- a/template/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.env -.env.* -!.env.example -docker-compose.override.yml -.DS_Store -.idea diff --git a/template/.gitignore.jinja b/template/.gitignore.jinja new file mode 100644 index 0000000..2ea4c36 --- /dev/null +++ b/template/.gitignore.jinja @@ -0,0 +1,16 @@ +.env +.env.* +!.env.example +docker-compose.override.yml +.DS_Store +.idea +{% if layout == 'single' %}.venv/ +__pycache__/ +*.pyc +.ruff_cache/ +.pytest_cache/ +sessions/*.session* +node_modules/ +.svelte-kit/ +/build/ +{% endif %} diff --git a/template/.pre-commit-config.yaml.jinja b/template/.pre-commit-config.yaml.jinja index e1b7c44..eef3b45 100644 --- a/template/.pre-commit-config.yaml.jinja +++ b/template/.pre-commit-config.yaml.jinja @@ -1,7 +1,17 @@ repos: - repo: local - hooks:{% if not parts %} []{% endif %} -{% for part in parts %} - id: {{ part }}-fmt + hooks:{% if layout == 'parts' and not parts %} []{% endif %} +{% if layout == 'single' %} - id: fmt + name: fmt + entry: make fmt + language: system + pass_filenames: false + - id: check + name: check + entry: make check + language: system + pass_filenames: false +{% endif %}{% for part in parts %} - id: {{ part }}-fmt name: {{ part }} fmt entry: make -C {{ part }} fmt language: system diff --git a/template/docker-compose.yml.jinja b/template/docker-compose.yml.jinja deleted file mode 100644 index cc92863..0000000 --- a/template/docker-compose.yml.jinja +++ /dev/null @@ -1,7 +0,0 @@ -{% if parts %}include: -{% for part in parts %} - path: - - {{ part }}/docker-compose.yml - - {{ part }}/docker-compose.${COMPOSE_ENV:-local}.yml - project_directory: . -{% endfor %}{% else %}services: {} -{% endif %} diff --git a/template/{% if layout == 'parts' %}.env.example{% endif %}.jinja b/template/{% if layout == 'parts' %}.env.example{% endif %}.jinja new file mode 100644 index 0000000..919d6e4 --- /dev/null +++ b/template/{% if layout == 'parts' %}.env.example{% endif %}.jinja @@ -0,0 +1,2 @@ +{% if parts %}COMPOSE_FILE=docker-compose.yml{% for part in parts %}:{{ part }}/docker-compose.local.yml{% endfor %} +{% endif %} diff --git a/template/Makefile b/template/{% if layout == 'parts' %}Makefile{% endif %} similarity index 100% rename from template/Makefile rename to template/{% if layout == 'parts' %}Makefile{% endif %} diff --git a/template/{% if layout == 'parts' %}docker-compose.yml{% endif %}.jinja b/template/{% if layout == 'parts' %}docker-compose.yml{% endif %}.jinja new file mode 100644 index 0000000..322a6ce --- /dev/null +++ b/template/{% if layout == 'parts' %}docker-compose.yml{% endif %}.jinja @@ -0,0 +1,5 @@ +{% if parts %}include: +{% for part in parts %} - path: {{ part }}/docker-compose.yml + project_directory: . +{% endfor %}{% else %}services: {} +{% endif %}