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

168 lines
11 KiB
Markdown
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.
# 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 | нет | нет |
Команды:
```bash
./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/`)
— чистить?