make the deploy script survive an unfamiliar server

دو حالتی که فقط روی سرورِ واقعی پیش می‌آیند، نه اینجا.

اسکریپت‌های قدیمیِ activate به PS1 بدونِ محافظ دست می‌زنند و زیرِ set -u با
«unbound variable» کلِ دیپلوی را می‌خوابانند — venv اینجا سالم است ولی venv
سرور لزوماً نه، پس set -u دورِ همان یک خط موقتاً خاموش می‌شود.

بررسیِ سلامت فقط 127.0.0.1:8000 را می‌زد. اگر gunicorn روی سوکت یا پورتِ
دیگری باشد، دیپلویِ کاملاً موفق هم با پیامِ خطا تمام می‌شد. حالا آدرسِ
عمومی هم امتحان می‌شود و در پایان می‌گوید کدام آدرس‌ها را زده.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 00:53:43 +03:30
parent a3a47b459d
commit 39a9f435ac

View File

@@ -25,7 +25,17 @@ step() { printf '\n%s▸ %s%s\n' "$C_OK" "$1" "$C_OFF"; }
warn() { printf '%s⚠ %s%s\n' "$C_WARN" "$1" "$C_OFF"; } warn() { printf '%s⚠ %s%s\n' "$C_WARN" "$1" "$C_OFF"; }
fail() { printf '%s✖ %s%s\n' "$C_ERR" "$1" "$C_OFF" >&2; exit 1; } fail() { printf '%s✖ %s%s\n' "$C_ERR" "$1" "$C_OFF" >&2; exit 1; }
HEALTH_URL="${TADRISINO_HEALTH_URL:-http://127.0.0.1:8000/api/health}" # اگر TADRISINO_HEALTH_URL ست نباشد چند آدرس امتحان می‌شود: پورتِ محلی ممکن
# است فرق کند (سوکتِ یونیکس، پورتِ دیگر)، و در آن حالت دیپلویِ موفق هم پیامِ
# خطا می‌گرفت. آدرسِ عمومی نشان می‌دهد سرویس واقعاً از بیرون جواب می‌دهد.
if [ -n "${TADRISINO_HEALTH_URL:-}" ]; then
HEALTH_URLS=("$TADRISINO_HEALTH_URL")
else
HEALTH_URLS=(
"http://127.0.0.1:8000/api/health"
"https://api.math.tadrisino2.ir/api/health"
)
fi
# ─── ۱. کدِ تازه ──────────────────────────────────────────────────────────── # ─── ۱. کدِ تازه ────────────────────────────────────────────────────────────
if [ "${SKIP_PULL:-0}" != "1" ]; then if [ "${SKIP_PULL:-0}" != "1" ]; then
@@ -39,8 +49,12 @@ printf ' کامیتِ فعلی: %s\n' "$(git rev-parse --short HEAD) $(git log
# ─── ۲. محیطِ پایتون ──────────────────────────────────────────────────────── # ─── ۲. محیطِ پایتون ────────────────────────────────────────────────────────
step "فعال‌سازیِ محیطِ مجازی" step "فعال‌سازیِ محیطِ مجازی"
if [ -d venv ]; then if [ -d venv ]; then
# set -u موقتاً خاموش: اسکریپت‌های activate قدیمی به PS1 بدونِ محافظ دست
# می‌زنند و زیرِ set -u با «unbound variable» کلِ دیپلوی را می‌خوابانند.
set +u
# shellcheck disable=SC1091 # shellcheck disable=SC1091
source venv/bin/activate source venv/bin/activate
set -u
printf ' venv فعال شد\n' printf ' venv فعال شد\n'
elif [ -n "${VIRTUAL_ENV:-}" ]; then elif [ -n "${VIRTUAL_ENV:-}" ]; then
printf ' از venv فعالِ فعلی استفاده می‌شود: %s\n' "$VIRTUAL_ENV" printf ' از venv فعالِ فعلی استفاده می‌شود: %s\n' "$VIRTUAL_ENV"
@@ -152,19 +166,22 @@ fi
# ─── ۸. آیا واقعاً بالا آمد؟ ─────────────────────────────────────────────── # ─── ۸. آیا واقعاً بالا آمد؟ ───────────────────────────────────────────────
step "بررسیِ سلامت" step "بررسیِ سلامت"
printf ' %s\n' "$HEALTH_URL" CODE=000; BODY=""
for attempt in 1 2 3 4 5 6 7 8 9 10; do for attempt in 1 2 3 4 5 6 7 8 9 10; do
# یک درخواست، نه دو تا: دو فراخوانیِ جدا می‌توانست دو وضعیتِ متفاوت ببیند. for url in "${HEALTH_URLS[@]}"; do
RESPONSE="$(curl -s -m 10 -w '\n%{http_code}' "$HEALTH_URL" 2>/dev/null || printf '\n000')" # یک درخواست، نه دو تا: دو فراخوانیِ جدا می‌توانست دو وضعیتِ متفاوت ببیند.
CODE="${RESPONSE##*$'\n'}" RESPONSE="$(curl -s -m 10 -w '\n%{http_code}' "$url" 2>/dev/null || printf '\n000')"
BODY="${RESPONSE%$'\n'*}" CODE="${RESPONSE##*$'\n'}"
if [ "$CODE" = "200" ]; then BODY="${RESPONSE%$'\n'*}"
printf '%s✓ سرویس سالم بالا آمد.%s\n' "$C_OK" "$C_OFF" if [ "$CODE" = "200" ]; then
printf '%s\n' "$BODY" | python -m json.tool 2>/dev/null | sed 's/^/ /' || printf ' %s\n' "$BODY" printf '%s✓ سرویس سالم بالا آمد%s (%s)\n' "$C_OK" "$C_OFF" "$url"
exit 0 printf '%s\n' "$BODY" | python -m json.tool 2>/dev/null | sed 's/^/ /' || printf ' %s\n' "$BODY"
fi exit 0
fi
done
sleep 3 sleep 3
done done
printf ' آدرس‌های امتحان‌شده: %s\n' "${HEALTH_URLS[*]}" >&2
printf '%s✖ سرویس بعد از ۳۰ ثانیه هنوز سالم نیست (آخرین کد: %s)%s\n' "$C_ERR" "$CODE" "$C_OFF" >&2 printf '%s✖ سرویس بعد از ۳۰ ثانیه هنوز سالم نیست (آخرین کد: %s)%s\n' "$C_ERR" "$CODE" "$C_OFF" >&2
printf '%s\n' "$BODY" | head -c 600 >&2; echo >&2 printf '%s\n' "$BODY" | head -c 600 >&2; echo >&2