- TOOLS/README.md: раздел «Канонический пайплайн (порядок шагов)» и описание безопасной генерации (staging → атомарная замена, бэкапы, маркер .stand); - TOOLS/ARCHITECTURE.md: ссылки devops/… → TOOLS/config/<stand>/…; - HISTORY/2026-09-30_yaml_pipeline_hardening.md: полная история изменений (что было не так, что сделано, прогон по стендам, коммиты, проверки).
8.6 KiB
2026-09-30 — Ужесточение пайплайна генерации YAML (безопасная замена, чистка легаси)
Связанные материалы:
TOOLS/README.md(канонический пайплайн, порядок шагов),TOOLS/ARCHITECTURE.md(спецификация), память репозитория:pipeline-legacy.md.
Задача
- Разобрать, что в генерации YAML устарело.
- Перегенерировать YAML по всем стендам так, чтобы старое удалялось безопасно, а новое создавалось атомарно.
- Задокументировать всё, чтобы история изменений прослеживалась.
Команда пользователя: «делай как ПОЛОЖЕНО, как в 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и т.д.
Открытые вопросы (на решение владельца)
- Удалять ли отключённые легаси-скрипты (
10/11/12/13,02_..._template_v2) физически? TOOLS/config/services_list.txt(общий, «объединение») не используется ни одним профилем — удалять?- Нужна ли поддержка легаси-прокси
index.cfmв01иyaml-generator(сейчас сохранена как совместимость)?