commit 5bb12b0a4f354c737f5f057f120ca99ee144b4a4 Author: h Date: Tue Sep 8 19:15:15 2026 +0200 Initial template diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4befed3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +.idea diff --git a/README.md b/README.md new file mode 100644 index 0000000..12b5ec6 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# 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. + +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` +- `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 + +Application services carry the `services` profile, databases and other infrastructure carry `external`. + +```sh +copier copy --trust -d 'parts=["backend","frontend"]' +copier update -a .copier-answers.infra.yml +``` diff --git a/copier.yml b/copier.yml new file mode 100644 index 0000000..dbb9e64 --- /dev/null +++ b/copier.yml @@ -0,0 +1,23 @@ +_subdirectory: template +_templates_suffix: .jinja +_answers_file: .copier-answers.infra.yml +_envops: + keep_trailing_newline: true + +parts: + type: str + multiselect: true + help: Parts that live in their own directory with a docker-compose.yml and a Makefile + choices: + backend: backend + frontend: frontend + default: [] + +init_git: + type: bool + help: git init and install pre-commit hooks + default: true + +_tasks: + - "{% if _copier_operation == 'copy' and init_git %}git init -q{% else %}true{% endif %}" + - "{% if _copier_operation == 'copy' and init_git %}sh -c 'command -v pre-commit >/dev/null && pre-commit install || true'{% else %}true{% endif %}" diff --git a/template/.env.example b/template/.env.example new file mode 100644 index 0000000..2bcba39 --- /dev/null +++ b/template/.env.example @@ -0,0 +1 @@ +COMPOSE_ENV=local diff --git a/template/.gitignore b/template/.gitignore new file mode 100644 index 0000000..817009b --- /dev/null +++ b/template/.gitignore @@ -0,0 +1,6 @@ +.env +.env.* +!.env.example +docker-compose.override.yml +.DS_Store +.idea diff --git a/template/.pre-commit-config.yaml.jinja b/template/.pre-commit-config.yaml.jinja new file mode 100644 index 0000000..e1b7c44 --- /dev/null +++ b/template/.pre-commit-config.yaml.jinja @@ -0,0 +1,16 @@ +repos: + - repo: local + hooks:{% if not parts %} []{% endif %} +{% for part in parts %} - id: {{ part }}-fmt + name: {{ part }} fmt + entry: make -C {{ part }} fmt + language: system + files: ^{{ part }}/ + pass_filenames: false + - id: {{ part }}-check + name: {{ part }} check + entry: make -C {{ part }} check + language: system + files: ^{{ part }}/ + pass_filenames: false +{% endfor %} diff --git a/template/CLAUDE.md b/template/CLAUDE.md new file mode 100644 index 0000000..9333590 --- /dev/null +++ b/template/CLAUDE.md @@ -0,0 +1,16 @@ +## Code Principles +- **Simplicity**: Write simple, straightforward code +- **Readability**: Make code easy to understand +- **Performance**: Consider performance without sacrificing readability +- **Maintainability**: Write code that's easy to update +- **Reusability**: Create reusable components and functions +- **Less Code = Less Debt**: Minimize code footprint +- **NEVER write comments** - code should be self-documenting +- **Docstrings ONLY if explicitly asked** + +## Checking commands +After writing code, always run: +```shell +make fmt +make check +``` diff --git a/template/Makefile b/template/Makefile new file mode 100644 index 0000000..99bfc9a --- /dev/null +++ b/template/Makefile @@ -0,0 +1,28 @@ +PARTS := $(patsubst %/Makefile,%,$(wildcard */Makefile)) +SERVICES := docker compose --profile services +EXTERNAL := docker compose --profile external + +.PHONY: env external recreate rebuild restart logs down fmt check build + +env: + @test -f .env || cat .env.example $(addsuffix /.env.example,$(PARTS)) > .env + +external: + $(EXTERNAL) up -d + +recreate: external + $(SERVICES) up -d --force-recreate + +rebuild: build recreate + +restart: + $(SERVICES) restart + +logs: + $(SERVICES) logs -f --tail=100 + +down: + $(EXTERNAL) --profile services down + +fmt check build: + @for part in $(PARTS); do $(MAKE) -C $$part $@ || exit 1; done diff --git a/template/docker-compose.yml.jinja b/template/docker-compose.yml.jinja new file mode 100644 index 0000000..cc92863 --- /dev/null +++ b/template/docker-compose.yml.jinja @@ -0,0 +1,7 @@ +{% 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/{{ _copier_conf.answers_file }}.jinja b/template/{{ _copier_conf.answers_file }}.jinja new file mode 100644 index 0000000..d0f5d97 --- /dev/null +++ b/template/{{ _copier_conf.answers_file }}.jinja @@ -0,0 +1 @@ +{{ _copier_answers|to_nice_yaml -}}