refactor(config-test): срезан разбор Bash — он не ловил ничего

- Зачем:
  - проверка была сломана с рождения цели: bash -n со списком файлов
    разбирает только первый, остальные уходят ему в аргументы. Из пяти
    скриптов проверялся один, и за всё время этого никто не заметил.
  - чинить незачем: скрипты стенда запускают с той же машины, и
    синтаксическая ошибка вылезает при первом же запуске с номером строки.
    Учебной ценности в проверке нет — из неё не узнаёшь ничего, кроме того,
    что у bash есть ключ -n.
  - держалась она не строчкой, а двенадцатью: обход репозитория, временный
    файл со списком, mapfile и две ветки на пустой список.
- Что:
  - из scripts/config-test.sh убраны разбор Bash и весь аппарат сбора
    списка файлов; 53 строки стали 40.
  - разбор файлов DAG остался и получил комментарий с основанием: их на
    машине не запускает никто, обработчик разбирает их внутри контейнера, и
    ошибка всплывает не сообщением, а молча пропавшим DAG.
  - README и карта проверок больше не обещают проверку синтаксиса Bash.
  - в карте записано, почему проверку не стоит заводить заново.
- Проверка:
  - make config-test зелёный.
  - оставшийся разбор DAG краснеет: незакрытая скобка в dags/test_kafka.py
    роняет цель с SyntaxError и ненулевым кодом; файл восстановлен.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-06 16:59:44 +03:00
co-authored by Claude Opus 5
parent 4245daf3f1
commit 5492e6ff3d
3 changed files with 18 additions and 17 deletions
+2 -2
View File
@@ -105,8 +105,8 @@ Kafka по той же причине спрашивают снаружи. Её
описание кластера, макросы, связь с keeper, `ReplicatedMergeTree`, описание кластера, макросы, связь с keeper, `ReplicatedMergeTree`,
`Distributed`, очередь распределённых DDL и очистку временных таблиц. `Distributed`, очередь распределённых DDL и очистку временных таблиц.
`make config-test` проверяет Compose, синтаксис Bash и Python и пробельные `make config-test` проверяет Compose, синтаксис файлов DAG и пробельные ошибки
ошибки в diff без запуска стенда. в diff без запуска стенда.
Обычный рабочий цикл — `make config-test` и `make smoke`; остальные цели гоняют Обычный рабочий цикл — `make config-test` и `make smoke`; остальные цели гоняют
тогда, когда правка их касается. Что утверждает каждая проверка, нужен ли ей тогда, когда правка их касается. Что утверждает каждая проверка, нужен ли ей
+10 -1
View File
@@ -37,7 +37,7 @@ ClickHouse: строки в `ods.event` считает сам сервер и о
| `make lint` | Код генератора отформатирован и проходит ruff | не нужен | 0,4 с | | `make lint` | Код генератора отформатирован и проходит ruff | не нужен | 0,4 с |
| `make typecheck` | Типы генератора сходятся (ty) | не нужен | 0,5 с | | `make typecheck` | Типы генератора сходятся (ty) | не нужен | 0,5 с |
| `make test` | Генератор делает то, что обещает; схема события остаётся объявленным контрактом, а собранное из неё [описание выгрузки](../formats/clickstream-event.md) — свежим | не нужен | 40 с | | `make test` | Генератор делает то, что обещает; схема события остаётся объявленным контрактом, а собранное из неё [описание выгрузки](../formats/clickstream-event.md) — свежим | не нужен | 40 с |
| `make config-test` | Compose разбирается, Bash и Python синтаксически целы, в diff нет пробельных ошибок. О работоспособности не говорит ничего | не нужен | 1 с | | `make config-test` | Compose разбирается, файлы DAG синтаксически целы, в diff нет пробельных ошибок. О работоспособности не говорит ничего | не нужен | 1 с |
| `make smoke` | Стенд **собран**: службы живы, порты отвечают, подключения настроены друг на друга. Вширь и по касательной к каждой службе. Единственная цель, которая здесь правда смоук | нужен | 8 с | | `make smoke` | Стенд **собран**: службы живы, порты отвечают, подключения настроены друг на друга. Вширь и по касательной к каждой службе. Единственная цель, которая здесь правда смоук | нужен | 8 с |
| `make check-clickhouse` | Всё, что спрашивают **у ClickHouse** и он отвечает сам: макросы, шарды, реплики, путь в keeper, ключ шардирования, очередь распределённых DDL | нужен | 7 с | | `make check-clickhouse` | Всё, что спрашивают **у ClickHouse** и он отвечает сам: макросы, шарды, реплики, путь в keeper, ключ шардирования, очередь распределённых DDL | нужен | 7 с |
| `make check-services` | **Службы работают**: DAG запускается и доходит, топик создаётся и удаляется, Superset логинится и ходит в базу | нужен | 44 с | | `make check-services` | **Службы работают**: DAG запускается и доходит, топик создаётся и удаляется, Superset логинится и ходит в базу | нужен | 44 с |
@@ -163,3 +163,12 @@ Superset, Prometheus и Grafana смоук стучится с машины в
Семантика счётчиков Docker `OOMKilled` и `RestartCount`, на которой держится Семантика счётчиков Docker `OOMKilled` и `RestartCount`, на которой держится
`check_containers_survived`, снята отдельными контейнерами и записана в `check_containers_survived`, снята отдельными контейнерами и записана в
ADR 0004, раздел «Что проверено». ADR 0004, раздел «Что проверено».
Разбор Bash из `make config-test` срезан 6 августа 2026 года, и вместе с ним —
двенадцать строк обхода репозитория со списком файлов. Проверка была сломана
с рождения: `bash -n` со списком файлов разбирает только первый, остальные
уходят ему в аргументы, — то есть из пяти скриптов проверялся один, и за всё
время цели этого никто не заметил. Заводить её заново незачем: скрипты стенда
запускаются с той же машины, и синтаксическая ошибка вылезает при первом же
запуске с номером строки. Разбор файлов DAG остался и по другому основанию —
их на машине не запускает никто.
+6 -14
View File
@@ -4,7 +4,6 @@ set -euo pipefail
readonly ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" readonly ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
read -r -a COMPOSE_CMD <<<"${COMPOSE_BIN:-docker compose}" read -r -a COMPOSE_CMD <<<"${COMPOSE_BIN:-docker compose}"
readonly CACHE_DIR="$(mktemp -d)" readonly CACHE_DIR="$(mktemp -d)"
readonly SHELL_FILES_LIST="$CACHE_DIR/shell-files"
cleanup() { cleanup() {
rm -rf "$CACHE_DIR" rm -rf "$CACHE_DIR"
@@ -35,19 +34,12 @@ jq -e '
any($service.volumes[]; .source == "airflow_auth" and .target == "/opt/airflow/auth") and any($service.volumes[]; .source == "airflow_auth" and .target == "/opt/airflow/auth") and
any($service.volumes[]; .source == "airflow_logs" and .target == "/opt/airflow/logs") any($service.volumes[]; .source == "airflow_logs" and .target == "/opt/airflow/logs")
' >/dev/null <<<"$config_json" ' >/dev/null <<<"$config_json"
if ! find "$ROOT_DIR" \ # Файлы DAG на машине никто не запускает: их разбирает обработчик внутри
-path "$ROOT_DIR/.git" -prune -o \ # контейнера, и синтаксическая ошибка там всплывает не сообщением, а тем, что
-type f -name '*.sh' -print0 >"$SHELL_FILES_LIST"; then # DAG молча не появился в списке. Локальный разбор — единственная дешёвая
printf 'ОШИБКА: не удалось получить список файлов Bash для проверки.\n' >&2 # обратная связь. Скрипты стенда проверять так незачем: их запускают с этой же
exit 1 # машины, и ошибка вылезает при первом же запуске с номером строки.
fi
mapfile -d '' -t shell_files <"$SHELL_FILES_LIST"
if [[ "${#shell_files[@]}" -eq 0 ]]; then
printf 'ОШИБКА: не найдено ни одного файла Bash для проверки.\n' >&2
exit 1
fi
bash -n "${shell_files[@]}"
PYTHONPYCACHEPREFIX="$CACHE_DIR" uv run --no-project python -m compileall -q "$ROOT_DIR/dags" PYTHONPYCACHEPREFIX="$CACHE_DIR" uv run --no-project python -m compileall -q "$ROOT_DIR/dags"
git -C "$ROOT_DIR" diff --check git -C "$ROOT_DIR" diff --check
printf 'ЗЕЛЁНО: Compose, Bash, Python и пробельные ошибки diff проверены.\n' printf 'ЗЕЛЁНО: Compose, Python и пробельные ошибки diff проверены.\n'