Перейти к основному содержимому

ADR 0170 — Dev-compose становится brabo-dev, и dev отказывается подниматься рядом с установкой

Статус​

Accepted. Решение сопровождающего от 2026-09-27 (AT-173): "оба" — собственное имя для dev И защита. Ссылается на ADR 0150 (compose установки, который родился, утверждая, что у него name, отличный от dev) и ADR 0152 (важные тома). Не редактирует ни один из них.

Контекст​

Измерено 2026-09-19: docker/docker-compose.yml (dev) и docker/docker-compose.install.yml оба объявляли name: brabo. Комментарий compose установки утверждал обратное — "name diferente do compose de dev de propósito: os dois podem coexistir na mesma máquina" — и это было неправдой. Для Docker машина с установкой И checkout имела ОДИН проект: контейнеры (brabo-api-1, brabo-postgres-1…), сеть (brabo_default) и тома с одинаковыми именами (brabo_pgdata, brabo_neo4j_data, brabo_git_local_repos, brabo_project_workspaces…) были одними и теми же.

Три последствия, первое измерено:

  • подъём одного compose поверх другого ПЕРЕСОЗДАЁТ контейнеры другого и подключает их к его базе — база установки получила миграцию из dev;
  • scripts/dev/reset-total.sh делает DROP SCHEMA … CASCADE в Postgres проекта brabo — то есть стёр бы базу установки;
  • docker compose down одного роняет другой.

Продакшен-compose (docker-compose.prod.yml) уже был brabo-prod и сюда не входит.

Решение​

1. Dev-compose начинает называться brabo-dev. Контейнеры brabo-dev-<serviço>-1, сеть brabo-dev_default, тома brabo-dev_<chave>. Overlay наблюдаемости (docker-compose.observability.yml) повторяет имя, потому что name: ПОСЛЕДНЕГО -f побеждает, и другое значение там перенесло бы весь стек в другой проект; его Alloy фильтрует по com.docker.compose.project=brabo-dev.

Compose установки ОСТАЁТСЯ brabo. Это имя, которое уже есть у сделанных установок, и его смена отключила бы каждую от собственных томов при следующем обновлении — цена легла бы на того, кто никогда не читал этот репозиторий. Меняется сторона того, кто разрабатывает, кто читает CHANGELOG и имеет runbook.

2. Защита в preflight.mjs и reset-total.sh. Оба ОТКАЗЫВАЮТ, называя найденные контейнеры и down (без -v) каждого файла, когда на машине есть контейнер — в любом состоянии, docker ps -a, — чья метка com.docker.compose.project.config_files указывает на compose УСТАНОВКИ (docker-compose.install.yml или имя ассета brabo-install-compose.yml). И отказывают, когда dev-compose, как его вызывает скрипт, разрешил бы проект brabo (COMPOSE_PROJECT_NAME=brabo в .env или в окружении). В reset защита — ПЕРВЫЙ шаг, ещё до preflight, и отказ выходит как RESET NÃO COMEÇOU.

Критерий — ФАЙЛ метки, а не имя проекта: установка распознаётся при любом -p, и именно это делает защиту полезной против того, чего имя не решает, — dev-compose, поднятого с -p brabo вручную, COMPOSE_PROJECT_NAME и старого checkout с name: brabo (у которого нет этой защиты, но продолжение аварии которого НОВЫЙ checkout отвергает).

Мерило существует в ДВУХ местах, JS (scripts/dev/instalacao-na-maquina.mjs) и bash (recusar_se_ha_instalacao в scripts/dev/reset-total-lib.sh), потому что spec reset запускается с поддельным node в PATH и должен доказать, что сам скрипт отказывает. Оба задействованы соседними spec.

Неотвечающий Docker НЕ приводит к отказу: preflight говорит, что защита не выполнилась, и продолжает (up без Docker ничего не поднимет), а в reset build, ещё до первого эффекта, упал бы так же.

3. Миграция тех, кто уже разрабатывает: предупреждение, никогда отказ, никогда удаление. Следующий pnpm dev создаёт ПУСТЫЕ тома brabo-dev_*; данные остаются в brabo_*. Preflight ПРЕДУПРЕЖДАЕТ, когда находит том brabo_* с ключом, который ТОЛЬКО dev-compose объявляет (*_node_modules, engine_build/deps/mix/hex), — список ВЫВОДИТСЯ из двух файлов compose, никогда не копируется, — и отделяет, не утверждая, чьи они, тома с общим для обоих ключом (pgdata, neo4j_data, git_local_repos, project_workspaces…), которые могут принадлежать установке. Процедура копирования (том за томом, cp -a, при остановленном Postgres) или начала заново — в runbook, "Moving a dev environment to brabo-dev". Ни один скрипт не удаляет том.

Последствия​

  • Разработчик действует один раз (поэтому ветка — breaking/): роняет старый стек БЕЗ -v (docker compose -p brabo -f docker/docker-compose.yml down) и выбирает копировать данные или начать заново. Пока он этого не сделал, старый compose держит порты, и preflight говорит ровно это вместо port is already allocated.
  • Разработка на машине с установкой теперь требует сначала остановить установку (down без -v: тома и данные остаются, up -d возвращает её обратно). Это объявленная цена защиты по НАЛИЧИЮ, и её выбрал сопровождающий: раздельные имена уже делают сосуществование безопасным в обычном случае, но защита существует как раз для необычного случая — а защита, которая лишь смотрела бы на коллизию имён, пропустила бы старый checkout и ручной -p при остановленной установке. Запустить оба ОДНОВРЕМЕННО по-прежнему невозможно в любом случае: они публикуют одни и те же порты.
  • Осиротевший том brabo_* с общим ключом сам по себе неотличим между старым dev и установкой — предупреждение говорит это вместо утверждения. Runbook учит спрашивать (config_files контейнеров, исключительные ключи, была ли установка на машине).
  • Документация и команды, которые цитировали brabo-api-1, brabo-postgres-1, brabo-ollama-1, brabo_pgdata… в контексте DEV, стали цитировать brabo-dev-*. Те, что говорят об УСТАНОВКЕ (том brabo_project_workspaces, который измеряет install.sh, корень broker в установке), остаются как есть, потому что остаются правдой. Историческое повествование (старый CHANGELOG, принятые RN и ADR) не переписывается.
  • Метки pod локального Prometheus становятся brabo-dev-api-1/ brabo-dev-engine-1, реальным именем контейнера; ни один дашборд не фильтрует по значению pod, только группирует.