Files
orchestrator/docs/work-items/ORCH-104/04-test-plan.yaml
claude-bot be90632068
All checks were successful
CI / test (push) Successful in 58s
analyst(ET): auto-commit from analyst run_id=653
2026-06-12 10:29:36 +03:00

151 lines
10 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
work_item: ORCH-104
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-12
model_used: claude-opus-4-8
title: "Установочный скрипт для Lite — интерактивный установщик scripts/install_lite.py"
framework: pytest
scope: >
FR-1..FR-11 / AC-1..AC-12. Покрывается поведение установщика (чистые функции + step-движок
с инъекцией фейков HTTP/процессов) и анти-дрейф (stdlib-only, no-delete, reuse-bricks, doc-sync,
invariant snapshot). ВНЕ объёма тестов: реальная установка пакетов, реальный docker compose up,
реальные Plane/Gitea/Telegram (unit/integration детерминированы, без сети/docker/LLM — NFR-7).
notes: >
Зеркало паттернов tests/test_bootstrap_script.py и tests/test_lite_setup_doc.py: модуль грузится
через importlib; side-effects (subprocess/HTTP/getpass/input) инъектируются фейками; чистые
функции (parse_env/render_env/preflight_verdict/distro-команда/discovery/select) тестируются
изолированно. Полный регресс `pytest tests/ -q` обязан оставаться зелёным. Имена функций ниже —
ориентир по образцу bootstrap_bundle.py; финальные сигнатуры уточняет архитектор/разработчик.
tests:
# ---- FR-1 / AC-1: entry-point и режимы ----
- id: TC-01
type: integration
description: "plan-режим (дефолт) печатает план + preflight и НЕ делает мутаций (нет записи .env, нет compose up); exit 0 при чистых предусловиях, 2 при блокерах."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-02
type: unit
description: "build_plan() возвращает нормативный список шагов Lite в правильном порядке (preflight→deps→discovery→inputs→secrets→env→up→onboard→health)."
module: tests/test_install_lite_script.py
expected: PASS
# ---- FR-2 / AC-2: скан предусловий ----
- id: TC-03
type: unit
description: "preflight-вердикт: отсутствие docker/compose/node, занятый прод-порт, mismatch uid:gid владельца repos-dir → блокеры; полностью укомплектованный хост → блокеров нет."
module: tests/test_install_lite_script.py
expected: PASS
# ---- FR-3 / AC-3 / D-1: управляемая установка зависимостей ----
- id: TC-04
type: unit
description: "distro→команда: apt-хост даёт apt-команду установки, dnf-хост — dnf-команду; неизвестный дистрибутив → деградация на текстовую инструкцию (без команды-мутации)."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-05
type: integration
description: "remediation: при отказе оператора (ответ 'N') и при отсутствии TTY установщик НЕ выполняет установку, печатает инструкцию и возвращает exit 2 (никакой молчаливой root-мутации)."
module: tests/test_install_lite_script.py
expected: PASS
# ---- FR-4 / AC-4 / D-2: детект Plane/Gitea + выбор ----
- id: TC-06
type: unit
description: "discovery: по фейковым фактам docker ps/портов с 2 кандидатами Plane возвращается ранжированный список из 2; 0 кандидатов → пустой список (триггерит ручной фолбэк)."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-07
type: unit
description: "select_candidate: валидный индекс выбирает кандидата; индекс вне диапазона/пустой ввод → режим ручного ввода URL (never-raise)."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-08
type: unit
description: "detect never-raise: исключение в пробе docker/порта/URL деградирует в 'кандидатов нет' и не роняет установщик (NFR-3)."
module: tests/test_install_lite_script.py
expected: PASS
# ---- FR-5 / AC-5: живая верификация ввода ----
- id: TC-09
type: integration
description: "verify-before-write: фейк Plane/Gitea, отвечающий 401, отклоняет токен — значение НЕ пишется в .env; ответ 200 принимает и пишет. Telegram getMe ok:false → отклонение."
module: tests/test_install_lite_script.py
expected: PASS
# ---- FR-6 / FR-7 / AC-6 / AC-7: секреты и env ----
- id: TC-10
type: unit
description: "parse_env round-trip: KEY=value строки → словарь, комментарии/пустые игнорируются."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-11
type: unit
description: "render_env: ключи-override обновляются в каноне, комментарии сохранены, неизвестные ключи дописываются управляемым блоком; идемпотентно (повторный рендер стабилен)."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-12
type: integration
description: "секрет-гигиена: после прогона ни одно секрет-значение не встречается в собранном stdout/логе (маскирование); записанные .env/.env.watchdog имеют права 600."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-13
type: integration
description: "no-silent-overwrite: при уже заполненных секретах повторный apply без --force их не перетирает (значения стабильны); webhook-секреты выпускаются вызовом gen_secrets.py, а не собственным кодом."
module: tests/test_install_lite_script.py
expected: PASS
# ---- FR-9 / AC-7: онбординг кирпичом ----
- id: TC-14
type: integration
description: "onboard reuse: установщик вызывает onboard_project.py apply+verify субпроцессом (фейк), парсит merged ORCH_PROJECTS_JSON из отчёта и пишет его в .env; ручные пункты отчёта пробрасываются (exit 2)."
module: tests/test_install_lite_script.py
expected: PASS
# ---- FR-1 / FR-10 / AC-8 / AC-11: идемпотентность, health, no-TTY ----
- id: TC-15
type: integration
description: "идемпотентность: два apply подряд (фейки) → второй помечает шаги skipped, без дублей проекта/webhook, значения .env стабильны."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-16
type: integration
description: "no-TTY fail-closed: stdin не tty → manual_checkpoint печатает инструкцию и поднимает остановку → exit 2 (никакого зависания на input)."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-17
type: integration
description: "health-гейт: фейк отвечает 200 на /health и валидным JSON на /queue,/metrics → сводка PASS, exit 0; /health не 200 → exit 1 с диагностикой (нет ложного success)."
module: tests/test_install_lite_script.py
expected: PASS
# ---- AC-9 / AC-10 / INV: структурные анти-дрейф ----
- id: TC-18
type: unit
description: "stdlib-only + no-src-import: AST-скан install_lite.py — импорты только из разрешённого stdlib-набора; нет 'from src'/'import src' (зеркало test_bootstrap_script)."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-19
type: unit
description: "no-delete-ops: AST/regex-скан не находит деструктивных операций (docker … rm/down -v, rm -rf, git push --force, удаление веток) и хост-хардкодов (FORBIDDEN-набор test_no_host_hardcodes)."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-20
type: unit
description: "reuse-bricks / anti-fork: скрипт ссылается на gen_secrets.py и onboard_project.py; не несёт захардкоженного канона имён статусов Plane (FORBIDDEN_STATUS_NEEDLES) и собственной генерации секретов."
module: tests/test_install_lite_script.py
expected: PASS
- id: TC-21
type: unit
description: "invariant snapshot: STAGE_TRANSITIONS/QG_CHECKS не изменены этим PR (существующий снапшот-тест зелёный; ORCH-104 их не трогает)."
module: tests/test_install_lite_script.py
expected: PASS
# ---- AC-12: синхронизация документации ----
- id: TC-22
type: unit
description: "doc-sync: tests/test_lite_setup_doc.py ассертит, что LITE_SETUP.md ссылается на install_lite.py как рекомендованный путь; все существующие проверки дока (13 разделов, кирпичи, env key-sync, секрет-гигиена) остаются зелёными."
module: tests/test_lite_setup_doc.py
expected: PASS