From d211052914dc842e94bc46b49d6e5de9d7c3ad58 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Sat, 25 Jul 2026 13:52:00 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=B7=D0=B0=D0=B2=D0=B5=D0=B4=D1=91?= =?UTF-8?q?=D0=BD=20=D1=81=D0=BA=D0=BB=D0=B0=D0=B4=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D0=B2=D0=B5=D0=BD=D1=86=D0=B8=D0=B9,=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B2=D0=B0=D1=8F=20=E2=80=94=20=D0=BA=D0=B0=D1=82=D0=B5=D0=B3?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B8=20=D0=B4=D0=B8=D1=80=D0=B5=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B9=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docs/conventions/ с индексом: чем конвенция отличается от ADR и drafts, статусы (рекомендуемая / обязательная), когда заводить - app-directories.md: конфигурация / данные / кеш по принципу создания и ценности; из категорий выводится backup-targets - раздел «Конвенции» в AGENTS.md со ссылкой на склад --- AGENTS.md | 6 +++ docs/conventions/README.md | 46 ++++++++++++++++++ docs/conventions/app-directories.md | 73 +++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 docs/conventions/README.md create mode 100644 docs/conventions/app-directories.md diff --git a/AGENTS.md b/AGENTS.md index 6137ff9..2185249 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -115,6 +115,12 @@ uv run ansible-galaxy install --role-file requirements.yml - `gitleaks` — поиск секретов в staged-файлах. - Проверка что секретные файлы зашифрованы vault. +## Конвенции + +Договорённости о том, как делать однотипные вещи, живут в [`docs/conventions/`](docs/conventions) — одна конвенция на файл, у каждой статус (рекомендуемая / обязательная) и честный список уже существующих отступлений. Это правила на будущее, в отличие от [`docs/adr/`](docs/adr) (однажды принятые решения, постфактум и неизменяемо) и [`docs/drafts/`](docs/drafts) (черновики и хроника). Перед тем как заводить новое приложение или директорию — заглянуть туда. + +- [Категории директорий приложения](docs/conventions/app-directories.md) — содержимое `base_dir` делится на конфигурацию (восстанавливается плейбуком, бэкап не нужен), данные (создаёт приложение, бэкапить обязательно) и кеш (создаёт приложение, перегенерирует само). Из категорий механически выводится `backup-targets`. + ## Соглашения по коду - Отступы: 2 пробела для YAML/Jinja, 4 пробела в остальных файлах (`.editorconfig`). diff --git a/docs/conventions/README.md b/docs/conventions/README.md new file mode 100644 index 0000000..76385a0 --- /dev/null +++ b/docs/conventions/README.md @@ -0,0 +1,46 @@ +# Конвенции + +Склад договорённостей о том, **как делать однотипные вещи** в этом +репозитории. Одна конвенция — один файл. + +Конвенция описывает повторяющийся выбор: как называть директории, как +раскладывать данные, как оформлять шаблоны. Она отвечает на вопрос «как +принято», а не «что здесь происходит». + +Чем отличается от соседей: + +- [`../adr/`](../adr) — **решение**, принятое однажды и постфактум + («почему выбрали Authelia, а не Keycloak»). Запись неизменяема. +- [`../drafts/`](../drafts) — оперативная хроника и черновики («что + собираюсь сделать»). +- `conventions/` — **правило на будущее**, применяемое многократно. + Живой документ: правится, когда договорённость меняется. + +## Статус + +Каждая конвенция начинается со строки статуса: + +- **Рекомендуемая** — так стоит делать в новом коде; существующий код + переезжает по мере касания, отдельной кампанией не переписывается. +- **Обязательная** — нарушение считается ошибкой; по возможности + проверяется линтером или хуком, а не вниманием. + +Конвенция без механической проверки держится только на внимании — это +нормально для рекомендуемой и плохо для обязательной. + +## Когда заводить + +Когда одно и то же решение принимается третий раз и каждый раз чуть +по-другому. Единичный выбор — не конвенция; если он ещё и был спорным, +ему место в ADR. + +## Соглашения + +- Имя файла — kebab-case, по теме: `app-directories.md`. +- В теле честно перечислены отступления, которые уже есть в коде, — + иначе документ описывает не репозиторий, а пожелание. + +## Список + +- [Категории директорий приложения](app-directories.md) — конфигурация / + данные / кеш: делим по тому, кто создаёт и что будет при потере. diff --git a/docs/conventions/app-directories.md b/docs/conventions/app-directories.md new file mode 100644 index 0000000..7aa141f --- /dev/null +++ b/docs/conventions/app-directories.md @@ -0,0 +1,73 @@ +# Категории директорий приложения + +**Статус:** рекомендуемая. + +Директории приложения внутри `base_dir` делим на три категории по +принципу создания и ценности содержимого: + +- **конфигурация** — то, что восстанавливается прогоном плейбука, в том + числе секреты; +- **данные** — то, что генерирует приложение и что нужно бэкапить; +- **кеш** — то, что генерирует приложение и что не нужно бэкапить: + приложение перегенерирует заново. + +Цель — упростить оперирование данными. Категория сразу отвечает на два +вопроса, которые иначе приходится выяснять по коду приложения: **кто +создаёт** содержимое и **что будет, если его потерять**. + +## Категории + +| Категория | Директория | Создаёт | Потеря содержимого | Бэкап | +| --- | --- | --- | --- | --- | +| Конфигурация | `config/` | плейбук | `inv pl -- ` восстанавливает | не нужен | +| Данные | `data/` | приложение | невосполнима | обязателен | +| Кеш | `cache/` | приложение | приложение перегенерирует | не нужен | + +Тест на границе данных и кеша: что будет, если сделать `rm -rf` и +поднять приложение заново. Поднимется само и наверстает — кеш. Не +поднимется или поднимется пустым — данные. + +Конфигурацию бэкапить не только не нужно, но и не стоит: там лежат +секреты, а бэкапы уезжают в облако. Источник истины для конфигурации — +репозиторий и vault, а не снапшот restic. + +## Практика + +- Переменные плейбука — `config_dir`, `data_dir`, `cache_dir` внутри + `base_dir`; директории создаются одной задачей `Create application + internal directories`. +- Файл `backup-targets` выводится из категорий механически: в него идут + данные, не идут конфигурация и кеш. +- Монтирование в контейнер: конфигурацию — `:ro`, где приложение это + позволяет. Данные и кеш — на запись. +- `docker-compose.yml` остаётся в корне `base_dir`: туда смотрит + `project_src` модуля `docker_compose_v2`. + +Пример, где категории разведены полностью, — `playbook-gramps.yml`: +`data` (база), `media` (файлы), `cache` (миниатюры и кеш отчётов), +`backups` (дампы). В `backup-targets` попадают первые три без `cache`. + +## Отступления, которые уже есть + +Конвенция рекомендуемая, поэтому список честный, а не пустой. + +- **`backups/`** — четвёртая директория рядом с тремя категориями. + Формально это производное от данных (дамп, который делает gobackup или + `pg_dump`), но именно она уезжает в restic, а сырые данные приложения — + не всегда. Держим отдельно и относим к данным. +- **`media/`** (gramps, outline) — это данные, просто вынесенные в + отдельную директорию: крупные файлы отделены от базы, чтобы их можно + было двигать между дисками независимо. +- **Конфигурация без `config/`** — она есть только у девяти плейбуков из + тридцати трёх, у остальных конфиги лежат прямо в `base_dir` рядом с + `docker-compose.yml`. Переезд по мере касания приложения, отдельной + кампанией не переписываем. +- **Легаси-раскладка `data/` под всё** — у части сервисов внутри `data/` + лежит и то, что по этой конвенции было бы кешем. Разделять имеет смысл + тогда, когда кеш заметен по объёму в бэкапе, а не ради самой схемы. + +## Связано + +- [ADR-2025-12-07](../adr/ADR-2025-12-07-app-data-on-separate-disk.md) — + почему всё это лежит на отдельном диске в `/mnt/applications`. +- `files/backups/backup-all.py` — оркестратор, читающий `backup-targets`.