Files
orchestrator/docs/operations/ONBOARDING.md

14 KiB
Raw Permalink Blame History

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, не падает).

  1. Проект: создаётся с identifier = --prefix. Уже существует → передай --plane-project-id <uuid> (ensure распознает и пропустит).

  2. Статусы — точные канонические имена (22, источник — plane_sync._PLANE_NAME_TO_KEY; опечатка = тихая деградация fail-closed веток):

    Статус Группа Статус Группа
    Backlog backlog In Review started
    Todo unstarted Blocked started
    To Analyse unstarted Approved started
    In Progress started Rejected started
    Analysis started Confirm Deploy started
    Architecture started Needs Input started
    Development started Done completed
    Code-Review started Cancelled cancelled
    Review started STOP cancelled
    Testing started Awaiting Deploy started
    Deploying started Monitoring after Deploy started

    ⚠️ Код-критично: STOP обязан быть в группе cancelled (иначе ветка отмены молча не активируется); в терминальных группах (completed/cancelled) — ТОЛЬКО Done/Cancelled/STOP, иначе terminal-detection ложно сочтёт живую задачу терминальной.

  3. Лейблы: autoApprove, autoDeploy, Bug (имена — из конфига оркестратора; их отсутствие = fail-safe ручной режим / полный цикл).

  4. 🖐 РУЧНОЙ ШАГ — порядок статусов на доске: drag-and-drop в UI (API не управляет порядком). Проверка: открой доску проекта — колонки в порядке конвейера.

  5. 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

  1. Репо --gitea-owner/--repo: создаётся пустым (auto_init=false; ветку main создаст initial push следующего слоя). Существует → skipped(exists).

  2. 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
    
  3. Branch protection main НЕ включать (ADR D10): required-approvals/status-checks ломают PR-merge API merge-актора конвейера (ложные HOLD). Защита держится конвенцией + скоупом токенов.


3. Слой kit: материализация + initial push

  1. 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)).
  2. Репо непустой → шаг помечается manual-step: 🖐 РУЧНОЙ ШАГ — занеси недостающие файлы обычным PR с ревью; поверх существующего контента ничего не пушится (BR-9).
  3. После рендера не должно остаться ни одного {{...}}: CLI падает на этом сам; повторная проверка — verify (скан плейсхолдеров в файлах репо).

4. Регистрация в реестре оркестратора

⚠️ САМЫЙ ВАЖНЫЙ РУЧНОЙ СЛОЙ. CLI .env прода НЕ правит и контейнер НЕ рестартит (инвариант NFR-2) — он только печатает готовую строку.

  1. 🖐 РУЧНОЙ ШАГ — env: возьми из отчёта apply строку ORCH_PROJECTS_JSON=[...полный merged-массив...] (существующие записи verbatim + новая в конец; строка уже провалидирована фактическим парсером реестра) и замени ею строку в .env оркестратора на хосте. Вставляется атомарно одной строкой — ручное слияние JSON не нужно.

  2. 🖐 РУЧНОЙ ШАГ — управляемый рестарт оркестратора: реестр строится при импорте, нужна перезагрузка процесса. 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   # реестр жив, конвейер пуст/цел
    
  3. TTL-self-heal статусов Plane (300с) рестарта НЕ требует: статусы/лейблы, созданные после регистрации, подхватятся сами.


5. Верификация

  1. 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 → exit 2 с перечнем.

  2. Smoke на песочнице (ADR D8) — контур: staging-оркестратор (порт 8501, изолированная БД ./data/staging) + одноразовый sandbox-проект (рекомендуемые имена: проект onboarding-smoke, префикс SMK, репо onboarding-smoke):

    1. Онборди sandbox самим CLI (слои 13 этого runbook).
    2. 🖐 РУЧНОЙ ШАГ: зарегистрируй sandbox в ORCH_PROJECTS_JSON .env.staging (не прода!) и перезапусти staging-контейнер (он свободен от прод-инварианта): docker compose --profile staging up -d orchestrator-staging.
    3. Создай тестовую задачу в sandbox-проекте → доведи до стадии analysis в песочнице.
    4. Критерий PASS: агент по своему промпту прочитал доку проекта (следы чтения CLAUDE.md/AGENTS.md в выводе) и записал артефакты в docs/work-items/SMK-…/ по канону PIPELINE_DOCS.md.
    5. Запротоколируй прогон в «Журнале 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.