diff --git a/README.md b/README.md index 7ee01d8..4924957 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,11 @@ core/ ядро; половины разъезжаются frontend/ шаблон панели: конфиг + четыре вкладки backend/server.ts шаблон бэкенда: конфиг + три демо-маршрута -scripts/update.sh копирует обе половины ядра в панель (npm run update) +Dockerfile один процесс и один образ: express отдаёт API и фронт scripts/new-panel.mjs заводит новую панель из шаблона (npm run new-panel) +scripts/release.sh split-ветки половин ядра для subtree (npm run release) scripts/doctor.mjs проверяет, что панель по стандарту (npm run doctor) +scripts/update.sh раскладывает ядро внутри шаблона (npm run update) ``` Половины лежат врозь не по вкусу, а потому что это две разные сборки: у них @@ -199,10 +201,10 @@ npm run new-panel -- admin-hub # → ../admin-hub, соседом m npm run new-panel -- admin-hub ~/work/hub # явный путь ``` -Скаффолдер копирует **`frontend/` и `backend/`**, но не `core/`: ядро в панель -приезжает копией через `npm run update`, а не форком. Панель кладётся соседом -ma7engine — именно там её найдёт перебор кандидатов в `update.sh`; переехав, она -найдёт ядро по `$MA7ENGINE`. +Панель — надстройка: она лежит подкаталогом продуктового репозитория +(`ghosthub/admin`, `awg-control/admin`), а не самостоятельным проектом. +Скаффолдер копирует **`frontend/` и `backend/`**, но не `core/`: ядро приходит +отдельно, через `git subtree` — см. следующий раздел. Что он делает за тебя — ровно то, что раньше правилось руками и потому забывалось: @@ -213,12 +215,50 @@ ma7engine — именно там её найдёт перебор кандид 3. **Демо-часть**: вкладки `hello` и `secrets` и маршруты `/api/demo/*` уезжают, `mountRoutes` остаётся пустым с образцом в комментарии. `docs` и `kit` остаются — обе самодостаточны, и панель запускается непустой. -4. **`.gitignore`** и `scripts/dev.sh` (обе половины одной командой). +4. **`.gitignore`**, `Dockerfile`, `.dockerignore` и `scripts/dev.sh`. Остаётся только **учётка и секрет** — `ADMIN_USER`, `ADMIN_PASS` (или `ADMIN_PASS_HASH`), `ADMIN_JWT_SECRET` в окружении бэкенда; без них ядро не даст процессу подняться. +### Ядро в продукт — `git subtree` + +У ядра две половины и два адресата, а `git subtree` работает с одним `prefix` за +раз, поэтому каждая половина выделяется в свою производную ветку: + +```sh +npm run release # core/browser → dist/browser, core/server → dist/server +``` + +В репозитории продукта, где панель лежит подкаталогом `admin/`: + +```sh +git subtree add --prefix=admin/frontend/src/core <ядро> dist/browser --squash +git subtree add --prefix=admin/backend/core <ядро> dist/server --squash + +git subtree pull --prefix=admin/frontend/src/core <ядро> dist/browser --squash +git subtree pull --prefix=admin/backend/core <ядро> dist/server --squash +``` + +`<ядро>` — путь к ma7engine либо URL его репозитория. + +**Почему поддерево, а не копирование.** `update.sh` сносил каталог целиком +(`rm -rf` + `cp -R`): локальная правка ядра в продукте исчезала молча, истории +не оставалось, и «панель разошлась с ядром» выяснялось постфактум. `git subtree` +делает настоящий merge — встречные правки одной строки дают конфликт **в момент +обновления**, а правку, сделанную в продукте, можно вернуть в ядро +(`git subtree push`). Ядро при этом лежит в репозитории продукта закоммиченным, +поэтому образ собирается из чистого checkout'а, без ma7engine рядом. + +Ветки `dist/*` полностью производные: руками не правятся и не мержатся обратно — +правится `core/`, после чего `npm run release` гоняется снова. + +**В самом ma7engine** ядро по-прежнему раскладывается копией (`npm run update` +из соседнего `core/`) — там источник лежит в том же репозитории, и поддерево +было бы поддеревом самого себя. Доктор различает эти два уклада и проверяет +каждый по своим правилам; в панели он ругается на оставшийся `update.sh`, потому +что тот затёр бы поддерево. + ### Проверка соответствия — `npm run doctor` Скаффолдер заводит панель по стандарту, доктор отвечает, соответствует ли она