110 lines
5.8 KiB
Bash
Executable file
110 lines
5.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
# ══════════════════════════════════════════════════════════════════════════
|
||
# DEPLOY лендинга simbiot.cil.by — ЗАПУСКАЕТСЯ НА ПРОДЕ (204.168.232.21).
|
||
#
|
||
# Одна команда с хоста харнеса (hermes-mon):
|
||
# ssh root@204.168.232.21 'bash -s' < scripts/deploy_landing.sh
|
||
#
|
||
# Что делает:
|
||
# 1) находит docroot в /etc/caddy/Caddyfile (блок simbiot.cil.by → root *);
|
||
# 2) бэкапит текущий index.html (index.html.bak-<date>, держит последние 10);
|
||
# 3) тянет канон из git.cil.by (токен — FORGEJO_PULL_TOKEN из /root/coop/.alfa_env,
|
||
# читает только read-scope; при отсутствии — просит в токен в stdin);
|
||
# 4) ставит файл, проверяет структуру (noscript чист, стили на месте);
|
||
# 5) печатает curl-проверку живого сайта.
|
||
#
|
||
# Канон: symbiot/simbiot-harness@master:docs/simbiot-landing-v2-live.html
|
||
# Runbook: docs/DEPLOY-LANDING.md. Idempotent: повторный запуск безопасен.
|
||
# t-2026-10-05 (day), эскалация e-261004110909-bd70b0.
|
||
# ══════════════════════════════════════════════════════════════════════════
|
||
set -euo pipefail
|
||
|
||
REPO_RAW="${REPO_RAW:-https://git.cil.by/symbiot/simbiot-harness/raw/branch/master/docs/simbiot-landing-v2-live.html}"
|
||
CADDYFILE="${CADDYFILE:-/etc/caddy/Caddyfile}"
|
||
LANDING_URL="${LANDING_URL:-https://simbiot.cil.by/}"
|
||
STAMP="$(date +%F-%H%M)"
|
||
|
||
echo "── [1/5] поиск docroot в $CADDYFILE"
|
||
DOCROOT="$(awk '
|
||
/^simbiot\.cil\.by[[:space:]]*\{/ {inb=1}
|
||
inb && /^[[:space:]]*root[[:space:]]+\*/ {
|
||
sub(/^[[:space:]]*root[[:space:]]+\*[[:space:]]+/, "")
|
||
sub(/[[:space:]]*$/, ""); print; exit
|
||
}
|
||
inb && /^\}/ {inb=0}
|
||
' "$CADDYFILE")"
|
||
|
||
if [ -z "$DOCROOT" ] || [ ! -d "$DOCROOT" ]; then
|
||
echo "FAIL: docroot не найден в Caddyfile (блок simbiot.cil.by → root * …)"
|
||
echo " покажи блок: grep -A6 'simbiot.cil.by' $CADDYFILE"
|
||
exit 2
|
||
fi
|
||
echo " docroot = $DOCROOT"
|
||
|
||
echo "── [2/5] бэкап текущего index.html"
|
||
if [ -f "$DOCROOT/index.html" ]; then
|
||
cp -p "$DOCROOT/index.html" "$DOCROOT/index.html.bak-$STAMP"
|
||
# держим последние 10 бэкапов
|
||
ls -1t "$DOCROOT"/index.html.bak-* 2>/dev/null | tail -n +11 | xargs -r rm -f --
|
||
echo " → index.html.bak-$STAMP"
|
||
else
|
||
echo " (index.html отсутствовал — свежая установка)"
|
||
fi
|
||
|
||
echo "── [3/5] загрузка канона из git.cil.by"
|
||
TOKEN="${FORGEJO_PULL_TOKEN:-}"
|
||
[ -z "$TOKEN" ] && [ -f /root/coop/.alfa_env ] && TOKEN="$(sed -n 's/^FORGEJO_PULL_TOKEN=//p' /root/coop/.alfa_env | tr -d '"' | tail -1)"
|
||
if [ -z "$TOKEN" ]; then
|
||
echo "FAIL: FORGEJO_PULL_TOKEN не найден (env / /root/coop/.alfa_env)."
|
||
echo " Перезапусти с токеном: ssh root@прод 'FORGEJO_PULL_TOKEN=<read-токен> bash -s' < scripts/deploy_landing.sh"
|
||
exit 3
|
||
fi
|
||
TMP="$(mktemp /tmp/landing.XXXXXX)"
|
||
trap 'rm -f "$TMP"' EXIT
|
||
if ! curl -fsSL -H "Authorization: token $TOKEN" "$REPO_RAW" -o "$TMP"; then
|
||
echo "FAIL: не скачался $REPO_RAW (токен без read:repository?)"
|
||
exit 3
|
||
fi
|
||
echo " скачано: $(wc -c <"$TMP") bytes"
|
||
|
||
echo "── [4/5] проверка содержимого перед установкой"
|
||
# NB: CSS-комментарии срезаются — в каноне есть текстовое "<noscript>" внутри /* */,
|
||
# иначе awk-диапазон ложно тянется до EOF и проверка врёт.
|
||
# Логика: python exit 1 = артефакт ЕСТЬ → ставим отказ.
|
||
if ! python3 - "$TMP" <<'PY'
|
||
import re, sys
|
||
h = open(sys.argv[1], errors='ignore').read()
|
||
h = re.sub(r'/\*.*?\*/', '', h, flags=re.S)
|
||
m = re.search(r'<noscript[^>]*>(.*?)</noscript>', h, flags=re.S)
|
||
sys.exit(1 if (m and ('moc-grid' in m.group(1) or '.shot' in m.group(1))) else 0)
|
||
PY
|
||
then
|
||
echo "FAIL: в каноне moc-grid/.shot внутри <noscript> — откат, ничего не ставим"
|
||
exit 4
|
||
fi
|
||
for pat in 'prefers-reduced-motion' 'og:image' '\.moc-grid{display:grid'; do
|
||
grep -q "$pat" "$TMP" || { echo "FAIL: в каноне нет '$pat' — откат"; exit 4; }
|
||
done
|
||
echo " проверки пройдены (noscript чист, стили/мета на месте)"
|
||
|
||
install -m 0644 "$TMP" "$DOCROOT/index.html"
|
||
echo " установлен $DOCROOT/index.html"
|
||
|
||
echo "── [5/5] проверка живого сайта (Caddy file_server отдаёт сразу)"
|
||
sleep 1
|
||
CODE="$(curl -s -o /dev/null -w '%{http_code}' "$LANDING_URL")"
|
||
echo " GET $LANDING_URL → $CODE"
|
||
# python exit 1 = артефакт всё ещё на проду → WARN.
|
||
if ! python3 - "$LANDING_URL" <<'PY'
|
||
import re, sys, urllib.request
|
||
h = urllib.request.urlopen(sys.argv[1], timeout=15).read().decode(errors="ignore")
|
||
h = re.sub(r'/\*.*?\*/', '', h, flags=re.S)
|
||
m = re.search(r'<noscript[^>]*>(.*?)</noscript>', h, flags=re.S)
|
||
sys.exit(1 if (m and ('moc-grid' in m.group(1) or '.shot' in m.group(1))) else 0)
|
||
PY
|
||
then
|
||
echo "WARN: прод всё ещё отдаёт старый файл (кэш CDN?) — проверь через минуту/Ctrl-F5"
|
||
else
|
||
echo "OK: прод отдаёт исправленную версию (showcase-стили вне noscript)"
|
||
fi
|
||
echo "── деплой завершён. Бэкап: $DOCROOT/index.html.bak-$STAMP"
|