Files
tf_provider/HISTORY/2026-09-30_yaml_pipeline_hardening.md
T
Repinoid 5e1a6f06bc docs(history): этап 2 — удаление мёртвого легаси (что удалено, что оставлено)
- раздел «Этап 2» с таблицей удалённых файлов и обоснованием;
- зафиксировано, что НЕ удалено и почему (index.cfm-совместимость,
  справочная копия DOCS_PIPELINE/publish-docs.sh, исторические документы);
- результаты проверок после удаления (bash -n, smoke-прогон 01 dev).
2026-09-30 09:53:57 +03:00

11 KiB
Raw Blame History

2026-09-30 — Ужесточение пайплайна генерации YAML (безопасная замена, чистка легаси)

Связанные материалы: TOOLS/README.md (канонический пайплайн, порядок шагов), TOOLS/ARCHITECTURE.md (спецификация), память репозитория: pipeline-legacy.md.

Задача

  1. Разобрать, что в генерации YAML устарело.
  2. Перегенерировать YAML по всем стендам так, чтобы старое удалялось безопасно, а новое создавалось атомарно.
  3. Задокументировать всё, чтобы история изменений прослеживалась.

Команда пользователя: «делай как ПОЛОЖЕНО, как в best practices».

Что было не так (до правок)

TOOLS/scripts/01_generate_yamls.sh

Место (до) Проблема
стр. 230 rm -f "$output_glob" старый YAML удалялся до генерации → при сбое API файл исчезал, новый не создавался (неатомарно per-service)
стр. 122 «Полной очистки нет» YAML исключённого сервиса оставался в каталоге и попадал в сборку
стр. 91 ls -t "${ROOT_DIR}"/*.token легаси-фолбэк токена: в корне токенов нет; поиск «последнего» мог подхватить чужой токен
стр. 109 API_ENDPOINT="${NUBES_API_ENDPOINT:-https://lk-api-gateway.ngcloud.ru/...}" молчаливый уход в PROD, если в профиле нет endpoint
стр. 167 svc_name="" имя всегда пустое, хотя шапка обещала парсинг из списка → лишний HTTP-запрос на каждый сервис (2 запроса вместо 1)
стр. 46–50 дубль SERVICES_FILE_DEFAULT (одинаковое присваивание в if)
шапка vs код «REQUEST_DELAY по умолчанию 0.2», в коде 0.5; путь вывода указан как provider/resources_yaml (устарел)

TOOLS/yaml-generator/internal/config/config.go

Место (до) Проблема
Load() стр. 33 свой дефолт endpoint = PROD gateway
loadToken() + findLatestToken() легаси-фолбэк «последний *.token в корне репо»
Load() стр. 60 путь filepath.Join(repoRoot, "devops", "config", "services_list.txt"), причём FindRepoRoot() возвращает каталог provider/ → путь заведомо не существовал

Легаси-скрипты

10_yaml_stability_run.sh, 11_yaml_stability_run_latest.sh, 12_generate_yamls_latest.sh, 13_generate_yamls_clean.sh, 02_generate_resources_and_docs_template_v2.sh — мертвы: зовут 01 без --profile (→ exit 2), ищут *.token в корне репо, а 13 вдобавок делал rm -f provider/resources_yaml/*.yaml. Ни один рабочий скрипт их не вызывает (ссылки есть только в исторических HISTORY/, NOTES/).

Что сделано

1. 01_generate_yamls.sh — безопасная запись по принципу staging → атомарная замена

Новый алгоритм:

staging = generated/<stand>/resources_yaml.staging.<pid>
   ↓ генерация всех сервисов пачкой per-service в staging
   ↓ при пустом failures:
       mv resources_yaml → resources_yaml.bak-<UTC>     (бэкап, ротация KEEP_BACKUPS=5)
       mv staging        → resources_yaml               (атомарный rename в том же FS)
   ↓ при непустом failures:
       замена ОТМЕНЯЕТСЯ, рабочий каталог не тронут, staging оставлен для разбора, exit 1

Прочие изменения:

  • каталог помечается маркером .stand; генерация в каталог чужого стенда запрещена (exit 2);
  • embed.go создаётся теперь в staging (обязательный go:embed *.yaml);
  • NUBES_API_ENDPOINT обязателен, иначе exit 2;
  • токен берётся только из NUBES_API_TOKEN/TOKEN_FILE; легаси-поиск удалён;
  • имя сервиса — из 2-го поля services_list.txt; лишний python-запрос удалён;
  • удалён дубль SERVICES_FILE_DEFAULT; синхронизированы комментарии.

2. yaml-generator/internal/config/config.go

  • NUBES_API_ENDPOINT обязателен (нет PROD-дефолта);
  • loadToken() больше не ищет *.token в корне репо; findLatestToken и getenvDefault удалены как мёртвые;
  • при отсутствии NUBES_SERVICE_ID требуется явный NUBES_SERVICES_FILE (угадывание пути удалено).

3. Легаси-скрипты отключены (fail-fast)

В начало каждого добавлен guard: сообщение DEPRECATED + exit 2. Файлы не удалены (удаление — отдельное решение владельца), но теперь они не могут сделать ничего вредного.

4. Документация

  • TOOLS/README.md — добавлен раздел «Канонический пайплайн (порядок шагов)» и описание безопасной генерации;
  • TOOLS/ARCHITECTURE.md — ссылки devops/… заменены на TOOLS/config/<stand>/…;
  • память репозитория — pipeline-legacy.md уточнена.

Прогон по всем стендам (результат)

Токены проверены прямыми запросами к API (с браузерным User-Agent, иначе DDoS-Guard отдаёт 403):

Стенд Endpoint HTTP YAML после генерации Stale Failures
dev lk-api-gateway-dev.ngcloud.ru 200 40 нет нет
test lk-api-gateway-test.ngcloud.ru 200 36 нет нет
prod lk-api-gateway.ngcloud.ru 200 35 нет нет

Команды:

./TOOLS/scripts/01_generate_yamls.sh --profile TOOLS/config/dev
./TOOLS/scripts/01_generate_yamls.sh --profile TOOLS/config/test
./TOOLS/scripts/01_generate_yamls.sh --profile TOOLS/config/prod

Проверка целостности: diff -rq нового каталога dev с бэкапом даёт различия только в случайных default-суффиксах, которые API генерирует при каждом запросе (db-ievgpdvu → db-ujama5rb, flask-seqtiq3t → flask-xwfdxdqh и т.п.) — структурной регрессии нет. Это же объясняет, почему побайтовое сравнение двух прогонов не может быть использовано как «детектор дрейфа».

Коммиты

  • 12b3932 — fix(tools): безопасная генерация YAML — staging + атомарная замена, без легаси-фолбэков
  • ad4daab — chore(tools): легаси-скрипты генерации отключены (fail-fast DEPRECATED)

Проверки

  • bash -n для 01_generate_yamls.sh и всех guard-скриптов — OK;
  • go vet ./... + go build для yaml-generator — OK;
  • guard отдаёт exit 2;
  • прогон dev/test/prod — 0 failures, stale отсутствует, staging не остаётся;
  • бэкапы создаются: generated/dev/resources_yaml.bak-20260930T063152Z и т.д.

Этап 2 — удаление мёртвого (по команде «удаляй всё старое, аккуратно»)

Удалено (1e796c8) — 100% мёртвый код/данные, ничего их не вызывает:

Файл Почему удалён
TOOLS/scripts/10_yaml_stability_run.sh зовёт 01 без --profile (exit 2), ищет *.token в корне
TOOLS/scripts/11_yaml_stability_run_latest.sh цепочка на 10, та же поломка
TOOLS/scripts/12_generate_yamls_latest.sh зовёт 01 без --profile, ищет *.token в корне
TOOLS/scripts/13_generate_yamls_clean.sh цепочка на 12 + делал rm -f provider/resources_yaml/*.yaml
TOOLS/scripts/02_generate_resources_and_docs_template_v2.sh легаси-дубль канонического 02_generate_resources_and_docs_v2.sh
TOOLS/config/services_list.txt (общий) код его не читает; как «объединение» устарел: активный 27 (в test/prod — «нет в UI»), нет 87/88/97/153, которые есть в dev

Проверка «ничего не вызывает»: grep по всему репо находил ссылки только в исторических HISTORY/, NOTES/, docs/ (не исполняются).

Правки ссылок (c822ae2): README.md, HOW_TO/README.md, HOW_TO/DEVOPS_BUILD_PIPELINE.md, HOW_TO/HOWTO_ADD_NEW_SERVICE.md (включая переписанный блок «Быстрый старт» с devops/ на ./TOOLS/scripts/*), DOCS_PIPELINE/README.md, scripts/publish-doc-page.sh, .gitignore.

Проверка после удаления: bash -n для всех TOOLS/scripts/*.sh и scripts/publish-doc-page.sh — OK; smoke-прогон 01 --profile TOOLS/config/dev — 40 YAML, замена атомарная, бэкап создан.

Не удалено (осознанно):

  • поддержка легаси-прокси index.cfm в 01 и yaml-generator — это совместимость с работающими пользователями старого API (провайдер v5.0.75, secrets/stands.md);
  • DOCS_PIPELINE/publish-docs.sh — сам файл помечен «справочная копия, не подменяет пайплайн»;
  • HISTORY/, NOTES/, docs/ — исторические документы (в них devops/ и легаси-скрипты упоминаются как история, это нормально);
  • scripts/*.py и s3_notification_example.sh — ручные утилиты, вызываются вручную.

Открытые вопросы (на решение владельца)

  1. Поддержка легаси-прокси index.cfm: оставляем или выпиливаем (README уже помечает закрытые API как «не использовать»)?
  2. Прочие .gitignore-паттерны мёртвых каталогов (universal_rebuild/*, provider/generated/) — чистить?