refactor(smoke): срезаны проверки стенда, не служащие менти

- Зачем:
  - проверок стало больше, чем продукта, и росли они из критериев приёмки,
    а не из учебной ценности (#56).
- Что:
  - удалены tests/dag-probes-unit.py, tests/stand-smoke-guards.sh,
    tests/stand-smoke-static.sh и tests/smoke-guards.sh вместе с целью
    make smoke-guards и запуском юнит-тестов в scripts/config-test.sh.
  - из scripts/stand-smoke.sh убран check_env_consistency, туда же переехал
    check_keeper_runtime; счёт проверок остался 25.
  - в пробниках свёрнуты функции _assert_*, комментарий про отложенный импорт
    переписан на причину из документации Airflow и продублирован в test_kafka.
- Проверка:
  - make config-test, make up, make smoke, make smoke-cluster.
This commit is contained in:
2026-08-06 13:06:44 +03:00
parent 6afa26b7be
commit 66490d124e
10 changed files with 102 additions and 920 deletions
-14
View File
@@ -48,20 +48,6 @@ if [[ "${#shell_files[@]}" -eq 0 ]]; then
fi
bash -n "${shell_files[@]}"
PYTHONPYCACHEPREFIX="$CACHE_DIR" uv run --no-project python -m compileall -q "$ROOT_DIR/dags"
unit_status=0
unit_output="$(
PYTHONPYCACHEPREFIX="$CACHE_DIR" \
uv run --no-project python "$ROOT_DIR/tests/dag-probes-unit.py" 2>&1
)" || unit_status=$?
printf '%s\n' "$unit_output"
if [[ "$unit_status" -ne 0 ]]; then
exit "$unit_status"
fi
if grep -Eq '^(Ran [0-9]+ tests|OK|FAILED)' <<<"$unit_output" ||
! grep -Eq '^ИТОГ: пройдено [0-9]+, ошибок 0$' <<<"$unit_output"; then
printf 'ОШИБКА: малые проверки пробников вывели итог не на русском языке.\n' >&2
exit 1
fi
git -C "$ROOT_DIR" diff --check
printf 'ЗЕЛЁНО: Compose, Bash, Python и пробельные ошибки diff проверены.\n'
+24 -111
View File
@@ -2,8 +2,6 @@
set -uo pipefail
readonly ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
readonly COMPOSE_FILE="$ROOT_DIR/compose.yaml"
readonly ENV_EXAMPLE="$ROOT_DIR/.env.example"
read -r -a COMPOSE_CMD <<<"${COMPOSE_BIN:-docker compose}"
readonly -a LONG_LIVED_SERVICES=(
clickhouse-keeper clickhouse-01 clickhouse-02 kafka postgres-metadata
@@ -36,114 +34,6 @@ fail() {
printf 'ОШИБКА: %s.\n' "$1" >&2
}
check_env_consistency() {
local LC_ALL=C
local content
local default
local depth
local env_value
local expression
local found_closing
local i
local inner
local joined
local j
local length
local line
local nested
local variable
local -A env_count=()
local -A env_values=()
local -a problems=()
local -A used=()
local -a expressions=()
if [[ ! -r "$COMPOSE_FILE" || ! -r "$ENV_EXAMPLE" ]]; then
fail 'compose.yaml или .env.example недоступны для чтения'
return
fi
# Разбираем только подстановки Compose и отдельно пропускаем $$ для команд контейнера.
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line%$'\r'}"
if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
variable="${BASH_REMATCH[1]}"
env_count["$variable"]=$(( ${env_count[$variable]:-0} + 1 ))
env_values["$variable"]="${BASH_REMATCH[2]}"
fi
done <"$ENV_EXAMPLE"
content="$(<"$COMPOSE_FILE")"
length="${#content}"
for ((i = 0; i < length - 1; i++)); do
if [[ "${content:i:2}" == '$$' ]]; then
i=$((i + 1))
continue
fi
if [[ "${content:i:2}" != '${' ]]; then
continue
fi
depth=1
found_closing=0
nested=0
for ((j = i + 2; j < length; j++)); do
if [[ "${content:j:2}" == '${' ]]; then
nested=1
depth=$((depth + 1))
j=$((j + 1))
elif [[ "${content:j:1}" == '}' ]]; then
depth=$((depth - 1))
if [[ "$depth" -eq 0 ]]; then
expressions+=("${content:i:j-i+1}")
found_closing=1
i="$j"
break
fi
fi
done
if [[ "$found_closing" -eq 0 ]]; then
problems+=("незакрытая подстановка у позиции ${i}")
break
fi
if [[ "$nested" -eq 1 ]]; then
problems+=("${expressions[-1]}: вложенные подстановки запрещены, используйте простой вид \${VAR:-значение}")
fi
done
for expression in "${expressions[@]}"; do
inner="${expression:2:${#expression}-3}"
if [[ "$inner" =~ ^([A-Za-z_][A-Za-z0-9_]*):-(.*)$ ]]; then
variable="${BASH_REMATCH[1]}"
default="${BASH_REMATCH[2]}"
used["$variable"]=1
if [[ "${env_count[$variable]:-0}" -ne 1 ]]; then
problems+=("${variable}: нужна ровно одна строка в .env.example")
continue
fi
env_value="${env_values[$variable]}"
if [[ "$env_value" != "$default" ]]; then
problems+=("${variable}: значение '${env_value}' не равно '${default}'")
fi
else
problems+=("${expression}: нет значения по умолчанию вида :-")
fi
done
for variable in "${!env_count[@]}"; do
if [[ -z "${used[$variable]+x}" ]]; then
problems+=("${variable}: не используется в compose.yaml")
fi
done
if [[ "${#problems[@]}" -eq 0 ]]; then
pass '.env.example совпадает со всеми значениями по умолчанию compose.yaml'
else
printf -v joined '%s; ' "${problems[@]}"
fail "расхождение .env.example и compose.yaml: ${joined%; }"
fi
}
check_host_dependencies() {
local command
local -a missing=()
@@ -184,6 +74,29 @@ check_container_health() {
fi
}
# Keeper — единственная служба, которой мало быть здоровой: она пишет журнал
# координации, и если запустить её от root или с чужим каталогом данных, файлы
# останутся с неверным владельцем и следующий запуск их не откроет. Предел на
# открытые файлы у неё свой: соединений много, и стандартной тысячи не хватает.
check_keeper_runtime() {
local keeper_user
local keeper_nofile
local keeper_owner
keeper_user="$(compose exec -T clickhouse-keeper id -un)"
keeper_nofile="$(compose exec -T clickhouse-keeper \
awk '$1 == "Max" && $2 == "open" && $3 == "files" {print $4}' /proc/1/limits)"
keeper_owner="$(compose exec -T clickhouse-keeper \
stat -c '%U:%G' /var/lib/clickhouse/coordination)"
if [[ "$keeper_user" == 'clickhouse' ]] && \
[[ "$keeper_nofile" -ge 262144 ]] && \
[[ "$keeper_owner" == 'clickhouse:clickhouse' ]]; then
pass 'keeper работает от clickhouse с nofile 262144 и своим каталогом данных'
else
fail "неверное окружение keeper: пользователь=${keeper_user}, nofile=${keeper_nofile}, владелец каталога=${keeper_owner}"
fi
}
published_port() {
local binding
local service="$1"
@@ -627,11 +540,11 @@ check_containers_survived() {
fi
}
check_env_consistency
if check_host_dependencies; then
for service in "${LONG_LIVED_SERVICES[@]}"; do
check_container_health "$service"
done
check_keeper_runtime
check_kafka_from_host
check_prometheus_targets
check_grafana_datasource