docs: заведён склад конвенций, первая — категории директорий приложения
- docs/conventions/ с индексом: чем конвенция отличается от ADR и drafts, статусы (рекомендуемая / обязательная), когда заводить - app-directories.md: конфигурация / данные / кеш по принципу создания и ценности; из категорий выводится backup-targets - раздел «Конвенции» в AGENTS.md со ссылкой на склад
This commit is contained in:
@@ -115,6 +115,12 @@ uv run ansible-galaxy install --role-file requirements.yml
|
|||||||
- `gitleaks` — поиск секретов в staged-файлах.
|
- `gitleaks` — поиск секретов в staged-файлах.
|
||||||
- Проверка что секретные файлы зашифрованы vault.
|
- Проверка что секретные файлы зашифрованы 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`).
|
- Отступы: 2 пробела для YAML/Jinja, 4 пробела в остальных файлах (`.editorconfig`).
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# Конвенции
|
||||||
|
|
||||||
|
Склад договорённостей о том, **как делать однотипные вещи** в этом
|
||||||
|
репозитории. Одна конвенция — один файл.
|
||||||
|
|
||||||
|
Конвенция описывает повторяющийся выбор: как называть директории, как
|
||||||
|
раскладывать данные, как оформлять шаблоны. Она отвечает на вопрос «как
|
||||||
|
принято», а не «что здесь происходит».
|
||||||
|
|
||||||
|
Чем отличается от соседей:
|
||||||
|
|
||||||
|
- [`../adr/`](../adr) — **решение**, принятое однажды и постфактум
|
||||||
|
(«почему выбрали Authelia, а не Keycloak»). Запись неизменяема.
|
||||||
|
- [`../drafts/`](../drafts) — оперативная хроника и черновики («что
|
||||||
|
собираюсь сделать»).
|
||||||
|
- `conventions/` — **правило на будущее**, применяемое многократно.
|
||||||
|
Живой документ: правится, когда договорённость меняется.
|
||||||
|
|
||||||
|
## Статус
|
||||||
|
|
||||||
|
Каждая конвенция начинается со строки статуса:
|
||||||
|
|
||||||
|
- **Рекомендуемая** — так стоит делать в новом коде; существующий код
|
||||||
|
переезжает по мере касания, отдельной кампанией не переписывается.
|
||||||
|
- **Обязательная** — нарушение считается ошибкой; по возможности
|
||||||
|
проверяется линтером или хуком, а не вниманием.
|
||||||
|
|
||||||
|
Конвенция без механической проверки держится только на внимании — это
|
||||||
|
нормально для рекомендуемой и плохо для обязательной.
|
||||||
|
|
||||||
|
## Когда заводить
|
||||||
|
|
||||||
|
Когда одно и то же решение принимается третий раз и каждый раз чуть
|
||||||
|
по-другому. Единичный выбор — не конвенция; если он ещё и был спорным,
|
||||||
|
ему место в ADR.
|
||||||
|
|
||||||
|
## Соглашения
|
||||||
|
|
||||||
|
- Имя файла — kebab-case, по теме: `app-directories.md`.
|
||||||
|
- В теле честно перечислены отступления, которые уже есть в коде, —
|
||||||
|
иначе документ описывает не репозиторий, а пожелание.
|
||||||
|
|
||||||
|
## Список
|
||||||
|
|
||||||
|
- [Категории директорий приложения](app-directories.md) — конфигурация /
|
||||||
|
данные / кеш: делим по тому, кто создаёт и что будет при потере.
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Категории директорий приложения
|
||||||
|
|
||||||
|
**Статус:** рекомендуемая.
|
||||||
|
|
||||||
|
Директории приложения внутри `base_dir` делим на три категории по
|
||||||
|
принципу создания и ценности содержимого:
|
||||||
|
|
||||||
|
- **конфигурация** — то, что восстанавливается прогоном плейбука, в том
|
||||||
|
числе секреты;
|
||||||
|
- **данные** — то, что генерирует приложение и что нужно бэкапить;
|
||||||
|
- **кеш** — то, что генерирует приложение и что не нужно бэкапить:
|
||||||
|
приложение перегенерирует заново.
|
||||||
|
|
||||||
|
Цель — упростить оперирование данными. Категория сразу отвечает на два
|
||||||
|
вопроса, которые иначе приходится выяснять по коду приложения: **кто
|
||||||
|
создаёт** содержимое и **что будет, если его потерять**.
|
||||||
|
|
||||||
|
## Категории
|
||||||
|
|
||||||
|
| Категория | Директория | Создаёт | Потеря содержимого | Бэкап |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| Конфигурация | `config/` | плейбук | `inv pl -- <app>` восстанавливает | не нужен |
|
||||||
|
| Данные | `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`.
|
||||||
Reference in New Issue
Block a user