Skip to content

fix(examples)/feat(runtime): путь volume для postgres:18+ (#26) + человекочитаемый нейминг контейнеров (#27) — 3.2.0 - #31

Merged
netrunner714 merged 2 commits into
mainfrom
feat/issue-26-27-pg18-volumes-and-naming
Nov 9, 2026
Merged

netrunner714 merged 2 commits into
mainfrom
feat/issue-26-27-pg18-volumes-and-naming

Conversation

@netrunner714

Copy link
Copy Markdown
Owner

Два независимых исправления в одной ветке: путь тома для postgres:18+ (#26) и человекочитаемый нейминг контейнеров (#27). Версия 3.2.0 (minor).


#26 — путь volume для postgres:18+ → /var/lib/postgresql

Образы postgres:18+ (docker-library/postgres#1259) хранят данные в каталогах по мажорным версиям и ожидают единое монтирование в /var/lib/postgresql. Legacy-путь .../data отправляет контейнер в рестарт-луп.

  • schemas/pegas.json — источник истины: примеры volumes переведены на путь 18+, description поля объясняет причину;
  • example.json перегенерирован из схемы (bun run scripts/gen-example.ts), README.md и docs/reference/contract.md обновлены; llms.txt уже содержал корректный путь;
  • guard-тест src/examples.postgres18.test.ts ловит откат к legacy-пути.

Подтверждено на живом развёртывании: контейнер 0a1b0e24d9-development-db-1 уже смонтирован в /var/lib/postgresql с PGDATA=/var/lib/postgresql/18/docker — legacy-путь сломал бы его.

#27 — нейминг pegas-<проект>-<сервис>-<сценарий>-<runtimeId>

Compose-проект ${runtimeId}-${scenario} давал имена вида 0a1b0e24d9-development-db-1: в docker ps нельзя было определить ни проект, ни сервис, ни принадлежность к Pegas.

pegas-815records-db-development-0a1b0e24d9           postgres:18-alpine   Up
pegas-815records-redis_queue-development-0a1b0e24d9  redis:7-alpine       Up
  • контейнеры — явный container_name в манифесте; compose-проект — pegas-<проект>-<сценарий>-<runtimeId>; runtimeId остаётся суффиксом (защита от коллизий checkout'ов + детерминизм имён → идемпотентность compose up);
  • новый модуль src/naming.ts — единственный источник истины схемы имён (+24 теста);
  • deploy --dry-run показывает compose-проект и containerNames;
  • сетевые алиасы <runtimeId>-<scenario>-<service> не меняются: на них ссылаются upstream'ы маршрутных файлов шлюза и развёрнутые значения pegas:// — маршруты и service discovery не требуют перенастройки.

Три ограничения, найденные эмпирически

1. Переименование проекта осиротило бы данные. Compose-проект задаёт префикс named-томов (0a1b0e24d9-development_815records-pgdata). Тома закреплены явным name: по исторической схеме. Проверено на реальном развёртывании: том существовал до правок и был переиспользован новым проектом без миграции.

2. Имя контейнера длиннее 63 символов перестаёт резолвиться по DNS. docker create принимает и 306 символов, compose config -q — тоже; но в поднятой сети 76 символов → getent hosts возвращает DNS_FAIL, 43 символа → DNS_OK (предел DNS-метки, RFC 1035). Длинные имена усекаются детерминированным дайджестом, сохраняя projectName и runtimeId целиком (первая реализация резала имя проекта в нечитаемое 8-0f45c4 — против самой цели issue, порядок приоритетов исправлен).

3. Латентный рассинхрон имени compose-проекта. deploy.ts вычислял ${runtimeId}-${env}, а манифест — pegas-${projectId}-${scenario}; при пустом PEGAS_ENV подставлялся development вместо scenarios[0]. Флаг --project-name перекрывает name: манифеста (проверено), поэтому дублирование убрано: createRuntimeCompose() возвращает scenario и composeProject.

Миграция сирот

Без неё после переименования старые контейнеры работали бы параллельно — --remove-orphans чужой compose-проект не видит. up точечно снимает контейнеры прежнего проекта по меткам pegas.project + pegas.scenario + com.docker.compose.project. Фильтр проверен на реальном legacy-контейнере: находит ровно его, чужие развёртывания не затрагиваются.


Проверки

Проверка Результат
bun run test 355 pass / 0 fail, покрытие 86,1% (порог 80%)
bun run typecheck чисто
bun run docs:check llms.txt и cli.md актуальны
bun run build собрано (index.js 219 KB, runtime.js 3,18 KB)
docker compose config -q / up / down пройдено на сгенерированном манифесте
docker ps / volume ls имена читаемы, существующие тома переиспользованы

E2E локально не запускался: он поднимает собственный gateway на 80/443, которые заняты живым pegas-gateway на этой машине. Все пробные контейнеры сняты, том с данными и контейнеры пользователя не затронуты.

Closes #26
Closes #27

Образы postgres:18+ (docker-library/postgres#1259) хранят данные в
каталогах по мажорным версиям и ожидают единое монтирование в
/var/lib/postgresql; legacy-путь .../data отправляет контейнер в
рестарт-луп.

- schemas/pegas.json: примеры volumes (properties.services и $defs.service)
  переведены на путь 18+; description поля volumes объясняет причину.
- example.json: перегенерирован из схемы (bun run scripts/gen-example.ts).
- README.md, docs/reference/contract.md: примеры и таблица полей обновлены.
- llms.txt уже содержал корректный путь — не тронут.
- src/examples.postgres18.test.ts: guard-тест — примеры в репозитории не
  монтируют legacy-путь, postgres:18-сервис эталона использует путь 18+.
…ервис>-<сценарий>-<runtimeId> (#27)

compose-проект `${runtimeId}-${scenario}` давал имена вида
`0a1b0e24d9-development-db-1`: в docker ps невозможно определить ни
проект, ни сервис, ни принадлежность к Pegas.

Схема 3.2.0:
- контейнер: pegas-<проект>-<сервис>-<сценарий>-<runtimeId> (container_name
  в манифесте); compose-проект: pegas-<проект>-<сценарий>-<runtimeId>;
- runtimeId — суффикс: защита от коллизий checkout'ов + детерминизм имён
  (идемпотентность compose up);
- предел DNS-метки 63 (RFC 1035) — реальное ограничение Docker: имя длиннее
  перестаёт резолвиться встроенным DNS (эмпирически: 76 → DNS_FAIL, 43 → OK).
  Длинные имена усекаются детерминированным дайджестом; усечение сохраняет
  projectName и runtimeId, режет сценарий и сервис;
- тома объявлены с явным именем <runtimeId>-<сценарий>_<том> (историческая
  схема compose): переименование проекта не осиротит данные существующих
  развёртываний — проверено на живом томе 0a1b0e24d9-development_815records-pgdata;
- миграция: up точечно снимает сирот прежнего compose-проекта по меткам
  pegas.project/pegas.scenario + com.docker.compose.project — --remove-orphans
  чужой проект не видит, без миграции старые контейнеры работали бы параллельно;
- сетевые алиасы <runtimeId>-<scenario>-<service> не меняются: на них
  ссылаются upstream'ы маршрутных файлов и значения pegas://;
- имя compose-проекта теперь только из манифеста (createRuntimeCompose
  возвращает scenario/composeProject): прежнее дублирование в runtime.ts
  расходилось с name: манифеста при пустом PEGAS_ENV;
- план deploy --dry-run показывает compose-проект и containerNames.

Новый модуль src/naming.ts — единственный источник истины схемы имён
(+ naming.test.ts, 24 теста). Проверено живым docker compose: config -q,
up/down, docker ps, volume ls — существующие тома и контейнеры не задеты.
Версия 3.2.0 (minor: имена контейнеров меняются, контракт и маршруты нет).
@netrunner714 netrunner714 self-assigned this Nov 9, 2026
@netrunner714
netrunner714 merged commit e8ce579 into main Nov 9, 2026
2 checks passed
@netrunner714
netrunner714 deleted the feat/issue-26-27-pg18-volumes-and-naming branch November 10, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant