14 KiB
ONBOARDING — turnkey-онбординг нового проекта (ORCH-009)
RUNBOOK. Полный чеклист подключения нового проекта к оркестратору одним проходом. Исполнитель — оператор; инструмент — CLI
scripts/onboard_project.py(режимыplan— дефолт/dry-run,apply,verify). Каждый шаг, который CLI выполнить не может, помечен 🖐 РУЧНОЙ ШАГ и снабжён командой проверки результата. Архитектура решения — см. «Ссылки» внизу.
Запуск CLI — из корня чекаута репо orchestrator, в venv с requirements.txt:
python3 scripts/onboard_project.py plan \
--name "My Project" --description "зачем проект" \
--repo my-project --prefix MP \
--stack "Python 3.12 + FastAPI" --test-cmd "pytest tests/ -q" \
--prod-port 8600 --staging-port 8601 \
--webhook-url https://openclaw.mva154.duckdns.org/orchestrator/webhook/gitea
plan печатает полный план без единой мутации (ни сети-POST, ни записи на диск);
apply — идемпотентный ensure (существующее → skipped(exists), ничего не удаляется);
exit-коды: 0 — чисто, 2 — есть manual-step/gap, 1 — ошибка.
0. Предусловия
Все значения — в .env на хосте (секреты в гит не попадают):
| Переменная | Зачем | Проверка |
|---|---|---|
ORCH_PLANE_API_TOKEN (+ORCH_PLANE_API_URL, ORCH_PLANE_WORKSPACE_SLUG) |
создание/чтение проекта, статусов, лейблов | curl -s -H "X-API-Key: $TOKEN" $URL/api/v1/workspaces/$SLUG/projects/ | head -c 200 |
ORCH_GITEA_TOKEN (+ORCH_GITEA_URL) |
создание репо + webhook | curl -s -H "Authorization: token $TOKEN" $URL/api/v1/user | head -c 200 |
ORCH_GITEA_WEBHOOK_SECRET |
HMAC webhook (переиспользуется, один на все репо) | есть строка в .env; нет → apply сгенерирует и выведет |
ORCH_PROJECTS_JSON |
текущий реестр — источник merged-вывода | grep ORCH_PROJECTS_JSON .env |
Токен Plane должен иметь право создавать проекты в workspace; токен Gitea — создавать репо и
hooks под выбранным owner (--gitea-owner, дефолт из конфига).
1. Слой Plane: проект + статусы + лейблы
Выполняет apply (или вручную при недоступности API CE — каждый отказ CLI помечает
manual-step, не падает).
-
Проект: создаётся с
identifier = --prefix. Уже существует → передай--plane-project-id <uuid>(ensure распознает и пропустит). -
Статусы — точные канонические имена (22, источник —
plane_sync._PLANE_NAME_TO_KEY; опечатка = тихая деградация fail-closed веток):Статус Группа Статус Группа Backlog backlogIn Review startedTodo unstartedBlocked startedTo Analyse unstartedApproved startedIn Progress startedRejected startedAnalysis startedConfirm Deploy startedArchitecture startedNeeds Input startedDevelopment startedDone completedCode-Review startedCancelled cancelledReview startedSTOP cancelledTesting startedAwaiting Deploy startedDeploying startedMonitoring after Deploy started⚠️ Код-критично:
STOPобязан быть в группеcancelled(иначе ветка отмены молча не активируется); в терминальных группах (completed/cancelled) — ТОЛЬКО Done/Cancelled/STOP, иначе terminal-detection ложно сочтёт живую задачу терминальной. -
Лейблы:
autoApprove,autoDeploy,Bug(имена — из конфига оркестратора; их отсутствие = fail-safe ручной режим / полный цикл). -
🖐 РУЧНОЙ ШАГ — порядок статусов на доске: drag-and-drop в UI (API не управляет порядком). Проверка: открой доску проекта — колонки в порядке конвейера.
-
Workspace-webhook: уже существует (один на весь workspace, создан на уровне workspace заранее) — CLI его НЕ создаёт, только напоминает проверить:
docker exec -e PGPASSWORD=plane plane-app-plane-db-1 psql -U plane -d plane -c \ "SELECT id, url, is_active FROM webhooks;"
2. Слой Gitea: репо + per-repo webhook
-
Репо
--gitea-owner/--repo: создаётся пустым (auto_init=false; веткуmainсоздаст initial push следующего слоя). Существует →skipped(exists). -
Per-repo webhook:
events: push/pull_request/status,content_type: json,branch_filter: *, URL =--webhook-url. Секрет переиспользуется изORCH_GITEA_WEBHOOK_SECRET(приёмник валидирует ОДИН глобальный секрет на все репо; новый секрет сломал бы HMAC существующих вебхуков). Секрета нет в env → CLI сгенерирует и выведет строку для.env— 🖐 РУЧНОЙ ШАГ: добавить её в.env(в гит не коммитить). Формат и проверка —docs/operations/SETUP_WEBHOOKS.md. Проверка:curl -s -H "Authorization: token $ORCH_GITEA_TOKEN" \ "$ORCH_GITEA_URL/api/v1/repos/<owner>/<repo>/hooks" | python3 -m json.tool -
Branch protection
mainНЕ включать (ADR D10): required-approvals/status-checks ломают PR-merge API merge-актора конвейера (ложные HOLD). Защита держится конвенцией + скоупом токенов.
3. Слой kit: материализация + initial push
applyрендерит kit (onboarding/repo-skeleton/, плейсхолдеры{{NAME}}изonboarding/placeholders.json) во временный каталог, докладывает live-copy канона (docs/_templates/16 скелетов +docs/_standards/3 стандарта — verbatim из текущего чекаута, BR-2 «канон не форкается») и пушит ТОЛЬКО в свежесозданный/пустой репо (единственный разрешённый push; коммитfeat: onboarding skeleton (ORCH-009 kit)).- Репо непустой → шаг помечается
manual-step: 🖐 РУЧНОЙ ШАГ — занеси недостающие файлы обычным PR с ревью; поверх существующего контента ничего не пушится (BR-9). - После рендера не должно остаться ни одного
{{...}}: CLI падает на этом сам; повторная проверка —verify(скан плейсхолдеров в файлах репо).
4. Регистрация в реестре оркестратора
⚠️ САМЫЙ ВАЖНЫЙ РУЧНОЙ СЛОЙ. CLI
.envпрода НЕ правит и контейнер НЕ рестартит (инвариант NFR-2) — он только печатает готовую строку.
-
🖐 РУЧНОЙ ШАГ — env: возьми из отчёта
applyстрокуORCH_PROJECTS_JSON=[...полный merged-массив...](существующие записи verbatim + новая в конец; строка уже провалидирована фактическим парсером реестра) и замени ею строку в.envоркестратора на хосте. Вставляется атомарно одной строкой — ручное слияние JSON не нужно. -
🖐 РУЧНОЙ ШАГ — управляемый рестарт оркестратора: реестр строится при импорте, нужна перезагрузка процесса. Self-hosting предупреждение: прод-контейнер один на ВСЕ проекты — рестарт = групповое окно (встаёт конвейер всех проектов). Выполняй осознанно: дождись тихого окна (
GET /queue— нет бегущих job), затем штатный рестарт поdocs/operations/INFRA.md. Проверка после рестарта:curl -s http://localhost:8500/health curl -s http://localhost:8500/queue | python3 -m json.tool | head -30 # реестр жив, конвейер пуст/цел -
TTL-self-heal статусов Plane (300с) рестарта НЕ требует: статусы/лейблы, созданные после регистрации, подхватятся сами.
5. Верификация
-
verify-режим CLI (read-only):python3 scripts/onboard_project.py verify --name ... --repo ... --prefix ... \ --plane-project-id <uuid> --stack ... --test-cmd ... --prod-port ... --staging-port ... \ --webhook-url https://openclaw.mva154.duckdns.org/orchestrator/webhook/giteaПроверяет: запись реестра парсится и совпадает по полям; все 22 статуса резолвятся (включая fail-closed
Confirm Deploy/STOP); лейблы на месте; webhook существует и активен; kit-файлы в репо (6 промптов,AGENTS.md,INFRA.md,_templates/_standards); нет неразрешённых плейсхолдеров. Любой gap → exit2с перечнем. -
Smoke на песочнице (ADR D8) — контур: staging-оркестратор (порт 8501, изолированная БД
./data/staging) + одноразовый sandbox-проект (рекомендуемые имена: проектonboarding-smoke, префиксSMK, репоonboarding-smoke):- Онборди sandbox самим CLI (слои 1–3 этого runbook).
- 🖐 РУЧНОЙ ШАГ: зарегистрируй sandbox в
ORCH_PROJECTS_JSON.env.staging(не прода!) и перезапусти staging-контейнер (он свободен от прод-инварианта):docker compose --profile staging up -d orchestrator-staging. - Создай тестовую задачу в sandbox-проекте → доведи до стадии analysis в песочнице.
- Критерий PASS: агент по своему промпту прочитал доку проекта (следы чтения
CLAUDE.md/AGENTS.mdв выводе) и записал артефакты вdocs/work-items/SMK-…/по канонуPIPELINE_DOCS.md. - Запротоколируй прогон в «Журнале smoke-прогонов» (ниже). Для приёмки ORCH-009 первый протокол обязателен.
6. Откат
CLI ничего не удаляет (BR-9) — откат всегда ручной и осознанный:
| Что создано | Как откатить | Проверка |
|---|---|---|
| Plane-проект (+статусы/лейблы) | удалить проект в UI Plane | проект исчез из списка workspace |
| Gitea-репо (+webhook) | удалить репо в UI/API Gitea (webhook умрёт вместе с ним) | GET /api/v1/repos/<owner>/<repo> → 404 |
| Строка реестра | убрать запись из ORCH_PROJECTS_JSON в .env + управляемый рестарт (см. слой 4, то же групповое окно) |
GET /queue — проекта нет в реестре |
| Sandbox-артефакты smoke | удалить sandbox-проект/репо после прогона (или архивировать) | см. выше |
Журнал smoke-прогонов
| Дата | Оператор | Параметры (проект/префикс/репо) | Контур | Результат (PASS/FAIL) | Протокол |
|---|---|---|---|---|---|
| — | — | — (первый прогон фиксируется при приёмке ORCH-009) | staging 8501 | — | — |
Ссылки
- Архитектура решения:
docs/work-items/ORCH-009/06-adr/ADR-001-turnkey-onboarding-kit-and-cli.md(D1…D11); сквозной ADR —docs/architecture/adr/adr-0035-turnkey-project-onboarding.md. - Устройство набора шаблонов и словарь плейсхолдеров:
onboarding/README.md. - Формат вебхуков:
docs/operations/SETUP_WEBHOOKS.md; топология и рестарты —docs/operations/INFRA.md.