fix(build): исключить SIGPIPE из релизных гейтов под pipefail
Поиск с флагом -q прекращает чтение на первом совпадении и закрывает свой конец
канала. Продюсер, которому осталось что писать, получает SIGPIPE и завершается
кодом 141, а `set -o pipefail` делает 141 статусом всей конструкции:
совпадение НАЙДЕНО -> продюсер оборван -> статус 141 -> «не найдено»
Для утвердительных проверок это ложный FAIL. Для отрицательных — «такой
конструкции в коде нет» — ложный PASS: запрещённая конструкция найдена, а гейт
зелёный. Отрицательными проверками закреплена половина инвариантов приёмки,
включая запрет обхода тестов и запрет `pnpm audit --prod`.
Порог резкий: пока вывод продюсера помещается в буфер канала (64 KiB на Linux),
он не блокируется и успевает завершиться раньше, чем потребитель начнёт читать.
Замер, 60 прогонов на размер: до 60 KiB — 0 отказов, ровно на 64 KiB — 58/60,
от 96 KiB — 60/60. То есть проверка выглядит исправной ровно до первого
источника крупнее буфера, а такие файлы в репозитории уже есть.
- 56 мест переведены на here-string: `grep -q PATTERN <<<"$content"`;
- продюсеры-команды (ss|awk, dpkg-query, /proc/cpuinfo, systemctl
list-unit-files) сначала читаются в переменную;
- введён code_has: десять отрицательных сканов держались на `|| true` внутри
code_without_comments, гасившем 141, — то есть на побочном эффекте
подавления ошибок, а не на заявленном свойстве;
- несуществующий путь в скане больше не означает успех: `2>/dev/null || true`
превращал опечатку в пустой вывод, а пустой вывод для проверки «этого в коде
нет» — это PASS. Проверка явная, а не через set -e: в контексте `! code_has`
bash отключает errexit на весь вызов;
- возврат пайплайна запрещён отдельной приёмкой.
This commit is contained in:
@@ -104,7 +104,12 @@ preflight() {
|
||||
local port
|
||||
for port in "$SERVER_PORT" "$STATS_PORT" "$AUTH_PORT" \
|
||||
"$ORIGIN_TCP_PORT" "$ORIGIN_UDP_PORT" "$FORWARD_TCP_PORT" "$FORWARD_UDP_PORT"; do
|
||||
if ss -H -lantu 2>/dev/null | awk '{print $5}' | grep -Eq "[:.]${port}\$"; then
|
||||
# Вывод собирается ДО поиска: `grep -Eq` обрывает чтение на первом
|
||||
# совпадении, и под `pipefail` SIGPIPE у продюсера превратил бы найденный
|
||||
# занятый порт в ненулевой статус, то есть в вывод «порт свободен».
|
||||
local sockets
|
||||
sockets="$(ss -H -lantu 2>/dev/null | awk '{print $5}')" || sockets=""
|
||||
if grep -Eq "[:.]${port}\$" <<<"$sockets"; then
|
||||
die "port $port is already in use"
|
||||
fi
|
||||
done
|
||||
@@ -134,7 +139,9 @@ wait_for_port() {
|
||||
local port="$1" proto_flag="$2" label="$3" attempts="${4:-30}"
|
||||
local i=0
|
||||
while [ "$i" -lt "$attempts" ]; do
|
||||
if ss -H "$proto_flag" 2>/dev/null | awk '{print $4}' | grep -Eq "[:.]${port}\$"; then
|
||||
local sockets
|
||||
sockets="$(ss -H "$proto_flag" 2>/dev/null | awk '{print $4}')" || sockets=""
|
||||
if grep -Eq "[:.]${port}\$" <<<"$sockets"; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
@@ -258,7 +265,9 @@ start_server() {
|
||||
cat "$WORK_DIR/server.log" >&2 || true
|
||||
die "server exited while starting"
|
||||
fi
|
||||
if ss -H -lun 2>/dev/null | awk '{print $4}' | grep -Eq "[:.]${SERVER_PORT}\$"; then
|
||||
local udp_sockets
|
||||
udp_sockets="$(ss -H -lun 2>/dev/null | awk '{print $4}')" || udp_sockets=""
|
||||
if grep -Eq "[:.]${SERVER_PORT}\$" <<<"$udp_sockets"; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
@@ -311,11 +320,11 @@ assert_production_share_uri_shape() {
|
||||
*) die "production share URI has an unexpected scheme: $production_uri" ;;
|
||||
esac
|
||||
|
||||
printf '%s' "$production_uri" | grep -q "obfs=$obfs_type" \
|
||||
grep -q "obfs=$obfs_type" <<<"$production_uri" \
|
||||
|| die "production share URI does not carry obfs=$obfs_type"
|
||||
printf '%s' "$production_uri" | grep -q 'insecure=0' \
|
||||
grep -q 'insecure=0' <<<"$production_uri" \
|
||||
|| die "production share URI must carry insecure=0"
|
||||
printf '%s' "$production_uri" | grep -q "sni=$SNI_NAME" \
|
||||
grep -q "sni=$SNI_NAME" <<<"$production_uri" \
|
||||
|| die "production share URI does not carry the SNI"
|
||||
|
||||
pass "production share URI keeps certificate verification enabled"
|
||||
@@ -350,7 +359,9 @@ start_client() {
|
||||
cat "$WORK_DIR/client.log" >&2 || true
|
||||
die "client exited while connecting via the generated share URI"
|
||||
fi
|
||||
if ss -H -ltn 2>/dev/null | awk '{print $4}' | grep -Eq "[:.]${FORWARD_TCP_PORT}\$"; then
|
||||
local tcp_sockets
|
||||
tcp_sockets="$(ss -H -ltn 2>/dev/null | awk '{print $4}')" || tcp_sockets=""
|
||||
if grep -Eq "[:.]${FORWARD_TCP_PORT}\$" <<<"$tcp_sockets"; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
|
||||
Reference in New Issue
Block a user