docs(install-vps): pin the update command to a real tag, and guard the pin form

INSTALL_VPS.md handed readers an update one-liner with a literal vX.Y.Z inside a
code block, and nothing nearby told them to substitute the number. RELEASE_PROCESS.md
step 3 says outright that users copy these one-liners verbatim, so a placeholder
there is a 404 waiting to happen. It is now pinned to v5.27.1 like every other pin
in the docs; that was the only non-numeric pin in the repository, measured across
all nine URL_DOCS files.

Check 6 could not have caught it, and that is the more interesting half. Its regex
requires three groups of digits, so a non-numeric pin never enters the sample at all
and the check stays green. Measured on five forms: v5.27.1 was seen, vX.Y.Z, v5.27,
vLATEST and main were not. v5.27 is the dangerous one - a plausible typo that looks
like a real tag and leads nowhere quietly.

Check 6b reads the same URL_DOCS sample but takes every occurrence along with the
leading v and requires the vX.Y.Z shape. The URL_DOCS line itself is left untouched
on purpose: the sample is the same one, and its byte form is an anchor for work in
flight on the Russian INSTALL_VPS.

The new check was fault-injected with all four previously invisible forms rather
than one, since a guard that has never fired is not a guard. Each of the four fails
it, and the tree returns to green after the revert.

Two suites pin the number of checks, so they move from 11 to 12.
This commit is contained in:
Ivan Bondarev 2026-08-25 12:20:01 +03:00
parent 310e4ef2a8
commit ee766fb4f8
4 changed files with 40 additions and 6 deletions

View file

@ -99,7 +99,7 @@ Per-command output formats and the compatibility promise: [ADVANCED.en.md JSON i
Updating to a newer installer release on a server that already has a supported version running: Updating to a newer installer release on a server that already has a supported version running:
```bash ```bash
wget -O install_amneziawg_en.sh https://raw.githubusercontent.com/bivlked/amneziawg-installer/vX.Y.Z/install_amneziawg_en.sh wget -O install_amneziawg_en.sh https://raw.githubusercontent.com/bivlked/amneziawg-installer/v5.27.1/install_amneziawg_en.sh
sudo bash ./install_amneziawg_en.sh --force sudo bash ./install_amneziawg_en.sh --force
``` ```

View file

@ -12,6 +12,12 @@
# Использование: # Использование:
# bash scripts/check-docs-consistency.sh # bash scripts/check-docs-consistency.sh
# #
# ⚠️ ДОБАВЛЯЕШЬ СЮДА НОВУЮ ПРОВЕРКУ - ПОДВИНЬ СЧЁТ В ДВУХ ТЕСТАХ.
# tests/test_v5153_docs_check.bats и tests/test_v5153_docs_check_slug.bats
# ассертят точную строку сводки вида "N passed, 0 failed". Любая добавленная
# проверка роняет оба файла, и связь эта ниоткуда не видна: сам скрипт про них
# не знает, а падение выглядит немотивированным.
#
# Проверки: # Проверки:
# 1. Внутренние markdown-ссылки (#anchor) резолвятся в этом же файле. # 1. Внутренние markdown-ссылки (#anchor) резолвятся в этом же файле.
# 2. CHANGELOG: у каждого version-heading есть reference-link; набор версий # 2. CHANGELOG: у каждого version-heading есть reference-link; набор версий
@ -24,6 +30,8 @@
# нет захардкоженного test-count baseline). # нет захардкоженного test-count baseline).
# 6. Pinned raw-URL теги в README/ADVANCED/INSTALL_VPS == SCRIPT_VERSION # 6. Pinned raw-URL теги в README/ADVANCED/INSTALL_VPS == SCRIPT_VERSION
# (CHANGELOG исключён - там теги исторические). # (CHANGELOG исключён - там теги исторические).
# 6b. Форма пина: все raw-URL теги имеют вид vX.Y.Z числами. Отдельная проверка
# потому, что регулярка #6 нечисловой пин не видит ВООБЩЕ (см. её комментарий).
# 7. ADVANCED: устаревшие IPv6 split-tunnel формулировки не вернулись # 7. ADVANCED: устаревшие IPv6 split-tunnel формулировки не вернулись
# (present-tense "не поддерживается / implies full-tunnel"; past-tense # (present-tense "не поддерживается / implies full-tunnel"; past-tense
# историческая заметка разрешена). # историческая заметка разрешена).
@ -258,6 +266,32 @@ for f in "${URL_DOCS[@]}"; do
done done
if [[ "$url_fail" -eq 0 ]]; then _ok "pinned raw-URL теги == SCRIPT_VERSION ($script_ver)"; else _bad "pinned raw-URL теги рассинхронизированы"; fi if [[ "$url_fail" -eq 0 ]]; then _ok "pinned raw-URL теги == SCRIPT_VERSION ($script_ver)"; else _bad "pinned raw-URL теги рассинхронизированы"; fi
# --- 6b. Форма пина: все raw-URL теги обязаны быть vX.Y.Z числами ---
# Проверка 6 выше сравнивает НАЙДЕННЫЕ ЧИСЛОВЫЕ теги со SCRIPT_VERSION, и это
# её единственная задача. Но её регулярка требует три группы цифр, поэтому
# нечисловой пин в выборку не попадает ВООБЩЕ и проверка остаётся зелёной.
# Замер 25 aug 2026: из пяти форм (v5.27.1, vX.Y.Z, v5.27, vLATEST, main) она
# видела ОДНУ. Опаснее всего v5.27 - правдоподобная опечатка из двух групп,
# выглядит настоящим тегом и молча ведёт в никуда.
# Живой случай: INSTALL_VPS.md отдавал команду обновления с буквальным vX.Y.Z
# внутри блока кода; docs/RELEASE_PROCESS.md шаг 3 прямо пишет, что пользователи
# копируют такие однострочники дословно.
# Здесь берём ВСЕ вхождения (`[^/]+`, вместе с ведущим v) и требуем форму.
# ⚠️ URL_DOCS намеренно переиспользуется как есть: выборка та же, менять её
# незачем, и её вид - якорь публикационного пакета русского INSTALL_VPS.
form_fail=0
for f in "${URL_DOCS[@]}"; do
[[ -f "$f" ]] || continue
while IFS= read -r pin; do
[[ -z "$pin" ]] && continue
if [[ ! "$pin" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo " $f: пин '$pin' не имеет формы vX.Y.Z (плейсхолдер, ветка или усечённый тег)" >&2
form_fail=1
fi
done < <(grep -oP 'raw\.githubusercontent\.com/bivlked/amneziawg-installer/\K[^/]+' "$f")
done
if [[ "$form_fail" -eq 0 ]]; then _ok "форма пинов raw-URL (все vX.Y.Z числами)"; else _bad "нечисловые пины в raw-URL"; fi
# --- 7. ADVANCED: устаревшие IPv6 split-tunnel формулировки не вернулись --- # --- 7. ADVANCED: устаревшие IPv6 split-tunnel формулировки не вернулись ---
# После переписывания IPv6-раздела (v5.15.1 split-tunnel + dual-stack корректно # После переписывания IPv6-раздела (v5.15.1 split-tunnel + dual-stack корректно
# сочетаются) present-tense заявления о неподдержке не должны появиться снова. # сочетаются) present-tense заявления о неподдержке не должны появиться снова.

View file

@ -17,9 +17,9 @@ TMPL_STALE_RE='placeholder:[[:space:]]*"e\.g\.,[[:space:]]*[0-9]+\.[0-9]+\.[0-9]
@test "T6: check-docs-consistency passes on the current repo" { @test "T6: check-docs-consistency passes on the current repo" {
run bash "$SCRIPT" run bash "$SCRIPT"
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
# 11 checks since the installer wget -O guard (#10) joined the OS x arch x # 12 checks since the pin-form guard (#6b) joined the installer wget -O
# prebuilt-target matrix check (#9). # guard (#10) and the OS x arch x prebuilt-target matrix check (#9).
[[ "$output" == *"11 passed, 0 failed"* ]] [[ "$output" == *"12 passed, 0 failed"* ]]
} }
@test "T6: script defines checks #7 and #8" { @test "T6: script defines checks #7 and #8" {

View file

@ -52,8 +52,8 @@ setup() {
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
} }
@test ".4 integration: docs-check still passes 11/11 with ROADMAP included" { @test ".4 integration: docs-check still passes 12/12 with ROADMAP included" {
run bash "$SCRIPT" run bash "$SCRIPT"
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
[[ "$output" == *"11 passed, 0 failed"* ]] [[ "$output" == *"12 passed, 0 failed"* ]]
} }