За другою рецензією:
* scripts/dbtest.sh писав у шапці «не напрямляйте на робочу базу» й
нічого для цього не робив — перевірено, пішов котити міграції на базу
з бойовим іменем. Тепер вимагає probe/test в імені.
* sendText ковтав помилку, тож журнал ескалацій писав «надіслано» на
сходинці, жодне повідомлення якої не дійшло. Три результати замість
двох: no_channels, failed, sent.
* stopped_at IS NULL рятував лише від ack; гасіння правилом і
ResolveMissing рядка драбини не чіпають, і сходинка дзвонила за
погашеним алертом. Додано перевірку стану алерту в тому ж UPDATE.
* escalate() блокував весь тік движка — мертвий вебхук одного кабінету
зупиняв обчислення правил усім. Винесено в RunEscalations.
* алерт, народжений під заглушенням, не сповіщався ніколи: ні при
народженні, ні коли вікно скінчилось. Тепер перехід suppressed→firing
сповіщається, а драбина рахує час від першого сповіщення.
* alr.rules.channel_ids приймав чужі канали, глушачи і сповіщення, і
драбину. Перевірка як для сходинок; DeleteChannel чистить посилання.
І перше, що зловив прогін проти справжньої бази: nil-зріз каналів їде
явним NULL повз DEFAULT '{}' — правило без каналів давало 500.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
106 lines
5.6 KiB
Bash
106 lines
5.6 KiB
Bash
#!/bin/sh
|
||
# Прогін тестів проти СПРАВЖНЬОЇ бази.
|
||
#
|
||
# ЧОМУ ЦЕ ОКРЕМИЙ СКРИПТ
|
||
#
|
||
# Тести проти бази мовчки пропускаються без NETPULSE_TEST_DSN — і саме
|
||
# тому вони півтора року нічого не перевіряли: `go test ./...` показував
|
||
# «ok», а всередині кожного з них стояв t.Skip. «Пропущено» в підсумку
|
||
# виглядає рівно як «пройдено», і це найдорожча тиха відмова в проєкті:
|
||
# перевірка ізоляції кабінетів, стелі тарифу, гасіння алертів і драбин
|
||
# ескалації існували, компілювались і не виконувались.
|
||
#
|
||
# scripts/check.sh лишається швидким (без Docker і без бази) — його
|
||
# ганяють на кожну правку. Цей скрипт повільніший і потребує Postgres,
|
||
# тож викликається окремо: перед розгортанням і в CI.
|
||
#
|
||
# БАЗА МУСИТЬ БУТИ ОДНОРАЗОВОЮ. Тести пишуть, видаляють і перемикають
|
||
# ролі, а перед ними ще й котяться міграції — зокрема ті, яких у робочій
|
||
# базі ще не має бути. І це не побажання в коментарі: рівно так гине
|
||
# бойова база, коли в профілі шелла лишився експортований
|
||
# NETPULSE_TEST_DSN зі вчорашнього налагодження. Тому нижче стоїть
|
||
# перевірка імені, а не заклик до обережності.
|
||
#
|
||
# ВИКОРИСТАННЯ
|
||
# scripts/dbtest.sh # підніме свій Postgres
|
||
# NETPULSE_TEST_DSN=... scripts/dbtest.sh # проти готової бази,
|
||
# # ім'я якої містить probe/test
|
||
#
|
||
set -u
|
||
|
||
SRC="$(cd "$(dirname "$0")/.." && pwd)"
|
||
OWN_DB=0
|
||
NAME=""
|
||
|
||
# Ім'я бази має саме казати, що вона одноразова. Перевірка навмисно
|
||
# дурна й невідмикна: розумніша (маркерна таблиця, прапорець згоди)
|
||
# перекладає рішення на людину рівно в той момент, коли людина поспішає.
|
||
guard_disposable() {
|
||
db=$(printf '%s' "$1" | sed -e 's/?.*$//' -e 's#.*/##')
|
||
case "$db" in
|
||
*probe*|*test*) return 0 ;;
|
||
esac
|
||
echo "!!! NETPULSE_TEST_DSN вказує на базу «$db»." >&2
|
||
echo " Тести пишуть, видаляють і котять міграції — база мусить бути" >&2
|
||
echo " одноразовою, і її імʼя має містити «probe» або «test»." >&2
|
||
echo " Якщо це чернетка — перейменуйте базу. Якщо ні — ви щойно мало" >&2
|
||
echo " не накотили міграції на робочу базу." >&2
|
||
exit 1
|
||
}
|
||
|
||
if [ -z "${NETPULSE_TEST_DSN:-}" ]; then
|
||
# Своя база на час прогону. Порт випадковий-таки ні: фіксований, але
|
||
# нетиповий, щоб не зіткнутись із локальним Postgres розробника.
|
||
PORT=${NETPULSE_TEST_PORT:-55433}
|
||
# Імʼя з номером процесу: два прогони поруч (другий термінал, дві
|
||
# задачі на одному раннері) інакше вбивали б бази один одному, і
|
||
# падіння виглядало б як помилка зʼєднання нізвідки.
|
||
NAME="netpulse-dbtest-$$"
|
||
echo "== піднімаю одноразовий Postgres :$PORT"
|
||
docker run -d --name "$NAME" -p "$PORT:5432" \
|
||
-e POSTGRES_USER=netpulse -e POSTGRES_PASSWORD=probe \
|
||
-e POSTGRES_DB=netpulse_probe \
|
||
timescale/timescaledb:2.17.2-pg16 >/dev/null || exit 1
|
||
OWN_DB=1
|
||
NETPULSE_TEST_DSN="postgres://netpulse:probe@127.0.0.1:$PORT/netpulse_probe?sslmode=disable"
|
||
export NETPULSE_TEST_DSN
|
||
n=0
|
||
until docker exec "$NAME" pg_isready -h 127.0.0.1 -U netpulse >/dev/null 2>&1; do
|
||
n=$((n+1)); [ "$n" -gt 60 ] && { echo "база не піднялась"; exit 1; }
|
||
sleep 1
|
||
done
|
||
else
|
||
guard_disposable "$NETPULSE_TEST_DSN"
|
||
fi
|
||
|
||
# Своя база зноситься лише після ЗЕЛЕНОГО прогону. Після червоного вона
|
||
# лишається: подивитись, що саме опинилось у таблицях, — єдиний спосіб
|
||
# зрозуміти половину падінь, а знесена база забирає цю можливість рівно
|
||
# тоді, коли вона потрібна.
|
||
cleanup() {
|
||
[ "$OWN_DB" = 1 ] || return 0
|
||
if [ "${rc:-1}" = 0 ]; then
|
||
docker rm -f "$NAME" >/dev/null 2>&1
|
||
else
|
||
echo
|
||
echo "база лишилась для розбору: docker exec -it $NAME psql -U netpulse netpulse_probe"
|
||
echo "прибрати: docker rm -f $NAME"
|
||
fi
|
||
return 0
|
||
}
|
||
trap cleanup EXIT INT TERM
|
||
|
||
echo "== накат міграцій"
|
||
( cd "$SRC/server" && NETPULSE_DSN="$NETPULSE_TEST_DSN" go run ./cmd/netpulse-migrate ) || exit 1
|
||
|
||
echo "== тести"
|
||
( cd "$SRC/server" && go test ./internal/... -count=1 )
|
||
rc=$?
|
||
|
||
echo
|
||
if [ "$rc" = 0 ]; then
|
||
echo "усе зелене проти бази"
|
||
else
|
||
echo "!!! тести проти бази не пройшли"
|
||
fi
|
||
exit $rc
|