Netpulse_SasS/scripts/check.sh
byrsapty ca143a616b
Some checks failed
CI / hygiene (push) Successful in 8s
CI / web (push) Successful in 59s
CI / server (push) Failing after 3m27s
CI / agent (push) Successful in 3m3s
Білінг, SLA, вбудовані правила, пісочниця установника, тести сторінок
П'ять паралельних задач. Найцінніше в них — не можливості, а знайдене.

0069 БІЛІНГ. Аудит 0009 показав, що перевірка ліміту не спрацювала б
жодного разу: isPlanLimit шукала слово «ліміт», а тригер писав
"device limit reached" англійською. Перше ж досягнення стелі дало б
клієнту 500 замість пояснення. Плюс три діри: тригер лише на INSERT
(стеля в 15 обходилась за чотири дії через архів), max_maps/max_agents/
max_users не перевіряло ніщо — тобто рівно те, чим відрізняються плани,
і license_keys була закрита політикою tenant_isolation з 0011, хоча
tenant_id там NULLABLE навмисно: головний сценарій self-hosted був
недосяжний.

Після закінчення ліцензії не вимикається нічого — замерзає лише ріст.
Моніторинг, що перестав моніторити через несплачений рахунок, це
аварія в мережі клієнта, спричинена нами.

0070 SLA. Джерелом обрано ts.icmp_1h, а не device_status_history:
остання не вміє сказати «ми не знали» — перехід пишеться лише при
зміні стану, тож доба мовчання зонда виглядає як доба роботи. Час
розкладено на чотири частини, і «немає даних» не додається ні до чого;
замість вибору між двома брехнями звіт каже, яку частку періоду він
бачив. Закритий період тримає тригер, а не домовленість у Go.

0071 ВІДПОВІДНІСТЬ. 20 правил, кожне прив'язане до родини: об'єднаний
вираз, що покриває Cisco й не покриває MikroTik, дав би «0 порушень» і
сховав сліпу пляму. Вендор не входить у перелік, доки для нього немає
зразка конфігу в тесті. TestBuiltinRulesAreNotAlwaysGreen вимагає, щоб
у кожного правила був конфіг, де воно спрацювало, І де ні.

ПІСОЧНИЦЯ УСТАНОВНИКА — та сама установка в ізольованому проєкті
compose. Знайшла дві справжні вади з трьох спроб:
  * healthcheck бази ходив unix-сокетом, а споживачі по TCP. При
    первинній ініціалізації Postgres слухає лише сокет — compose
    вважав базу здоровою, migrate отримував connection refused. На
    створеній базі цієї фази немає, тож вада чекала на першого клієнта;
  * у білому переліку модулів API не було traps і filecfg — зонд із
    приймачем трапів неможливо було зареєструвати взагалі.

ТЕСТИ СТОРІНОК: 137 → 252. Мережевий шар, права доступу, незворотні
дії, фільтри з адресного рядка. Підмінюється лише fetch і WebSocket —
api/client.ts працює справжній.
2026-08-27 21:17:23 +03:00

141 lines
6.8 KiB
Bash
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.

#!/usr/bin/env sh
#
# Усі перевірки NetPulse однією командою.
#
# Навіщо окремий скрипт, коли є .forgejo/workflows/ci.yml: раннера
# Forgejo досі немає, тобто CI не запускався жодного разу. Перевірка, яку
# нікому виконати, не ловить нічого — а та сама послідовність, запущена
# руками перед комітом, ловить уже сьогодні. Коли раннер зʼявиться, CI
# викликатиме ті самі кроки; розходитись їм нема з чого.
#
# Запуск:
# sh scripts/check.sh # усе
# sh scripts/check.sh web # лише веб
# sh scripts/check.sh go # лише server + agent
# sh scripts/check.sh repo # лише перевірки репозиторію
#
# На Windows — з Git Bash; PowerShell цей файл не виконує.
#
# Скрипт НЕ зупиняється на першій невдачі навмисно: інакше, щоб
# побачити три поламані місця, довелось би прогнати його тричі.
# Ненульовий код виходу все одно повертається — рівно для гачка
# pre-push і для CI.
set -u
# CDPATH= — не помилка з пробілом, а гасіння CDPATH: якщо він виставлений
# в оточенні, cd мовчки піде не туди, і скрипт перевірятиме чужий каталог.
# shellcheck disable=SC1007
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
cd "$ROOT" || exit 1
FAILED=""
PASSED=""
# Прогін одного кроку. Назва потрібна для підсумку: список «що саме
# впало» у кінці цінніший за чотириста рядків виводу вище.
step() {
name=$1
shift
printf '\n\033[1m== %s\033[0m\n' "$name"
if "$@"; then
PASSED="$PASSED|$name"
else
FAILED="$FAILED|$name"
fi
}
# gofmt -l друкує список файлів, а не код виходу: без явної перевірки
# порожнечі крива форма проїжджає в main непоміченою.
gofmt_check() {
bad=$(gofmt -l "$1")
if [ -n "$bad" ]; then
echo "не відформатовано (виправити: gofmt -w $1):"
echo "$bad"
# На Windows цей крок червоніє ще й від CRLF у робочій копії: gofmt
# вважає \r частиною рядка й пропонує переписати файл цілком. У
# репозиторії лежить LF (див. .gitattributes), тож на Linux-раннері
# той самий файл зелений. Різницю треба назвати вголос: інакше її
# «виправлять» через gofmt -w і закомітять зіпсовані переноси.
echo "якщо різниця в цілому файлі — це CRLF у робочій копії:"
echo " git ls-files --eol $1 | git add --renormalize ."
return 1
fi
echo "форма в порядку"
}
# Зонд їде на чуже залізо: перевіряємо, що збирається під усі платформи,
# які обіцяємо, а не лише під ту, де запустили скрипт.
agent_cross() {
out=${TMPDIR:-/tmp}/netpulse-crossbuild
mkdir -p "$out" || return 1
for target in linux/amd64 linux/arm64 linux/arm windows/amd64 darwin/arm64; do
os=${target%/*}
arch=${target#*/}
echo "-- $os/$arch"
( cd agent && CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" go build -trimpath \
-o "$out/netpulse-agent-$os-$arch" ./cmd/netpulse-agent ) || return 1
done
rm -rf "$out"
}
go_in() { ( cd "$1" && shift && "$@" ); }
check_go() {
step "server: gofmt" gofmt_check server
step "server: vet" go_in server go vet ./...
# Тести проти бази самі пропускаються без NETPULSE_TEST_DSN — локальний
# прогін не має ні піднімати Postgres, ні тим паче чіпати бойову базу.
step "server: тести" go_in server go test ./...
step "agent: gofmt" gofmt_check agent
step "agent: vet" go_in agent go vet ./...
step "agent: тести" go_in agent go test ./...
step "agent: крос-збірка" agent_cross
}
# Перевірки самого репозиторію — не коду, а того, як він лежить.
#
# Обидві ловлять поломки, яких не видно в diff і які проявляються вже на
# стенді: розходження каталогу профілів зі згенерованою міграцією і CRLF,
# що змінює sha256 тієї ж міграції. Чому саме так — у шапках
# scripts/check-eol.sh і db/profiles/build.py.
#
# Тут вони без --strict: у робочій копії на Windows CRLF цілком буває, і
# це попередження, а не привід не дати закомітити. У CI той самий скрипт
# викликається з --strict — там свіжий клон на Linux, і CRLF означав би
# зламане викачування.
check_repo() {
step "репозиторій: закінчення рядків" sh scripts/check-eol.sh
# python3 на Linux, python у Git Bash на Windows: різні імена одного
# й того самого, і вгадувати не треба — беремо той, що є.
py=python3
command -v python3 >/dev/null 2>&1 || py=python
step "репозиторій: каталог профілів" "$py" db/profiles/build.py --check
}
check_web() {
# npm ci лише коли залежностей немає: на кожному прогоні він викидає
# node_modules і ставить наново — хвилини замість секунд.
if [ ! -d web/node_modules ]; then
step "web: залежності" go_in web npm ci
fi
step "web: типи" go_in web npx tsc --noEmit
step "web: тести" go_in web npx vitest run
step "web: збірка" go_in web npx vite build
}
case "${1:-all}" in
web) check_web ;;
go) check_go ;;
repo) check_repo ;;
all) check_repo; check_go; check_web ;;
*) echo "невідомий набір: $1 (є: all, repo, go, web)"; exit 2 ;;
esac
printf '\n\033[1m== підсумок\033[0m\n'
echo "$PASSED" | tr '|' '\n' | sed '/^$/d' | sed 's/^/ ok /'
if [ -n "$FAILED" ]; then
echo "$FAILED" | tr '|' '\n' | sed '/^$/d' | sed 's/^/ ВПАЛО /'
exit 1
fi
echo "усе зелене"