make a deploy fail loudly when the service never restarted
سرور دو روز کدِ قدیمی را سرو کرد و هیچکس نفهمید. علتش این بود که `systemctl restart` شکست خورده بود ولی پروسهی قبلی هنوز بالا بود و همان ۲۰۰ را میداد — پس اسکریپت «✓ سرویس سالم بالا آمد» چاپ کرد و با کدِ صفر تمام شد. محتوا و فایلهای استاتیک هم روی دیسک بودند و سرو نمیشدند. حالا زمانِ بالا آمدنِ سرویس قبل و بعد مقایسه میشود. اگر عوض نشده باشد، ۲۰۰ گرفتن دیگر موفقیت حساب نمیشود و اسکریپت با خطا تمام میکند. نامِ عامِ `gunicorn` هم از فهرستِ حدسِ سرویس برداشته شد: روی سرورِ واقعی یک `gunicorn.service` هست که مالِ تیمِ دیگری است، و حدس زدنش یعنی ریاستارت کردنِ سرویسِ یک نفرِ دیگر. نامِ درستِ ما `gunicorn-mathapp` است. `api/health/` هم کنارِ `api/health` ثبت شد. پایشِ سرور شکلِ اسلشدار را صدا میزد و چون ثبت نبود، کسی روی سرور `config/urls.py` را دستی ویرایش کرده بود — و از آن به بعد هر `git pull` روی همان فایل گیر میکرد. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
34
deploy.sh
34
deploy.sh
@@ -33,7 +33,9 @@ if [ -n "${TADRISINO_HEALTH_URL:-}" ]; then
|
||||
else
|
||||
HEALTH_URLS=(
|
||||
"http://127.0.0.1:8000/api/health"
|
||||
"http://127.0.0.1:8000/api/health/"
|
||||
"https://api.math.tadrisino2.ir/api/health"
|
||||
"https://api.math.tadrisino2.ir/api/health/"
|
||||
)
|
||||
fi
|
||||
|
||||
@@ -150,18 +152,36 @@ SERVICE="${TADRISINO_SERVICE:-}"
|
||||
if [ -z "$SERVICE" ] && command -v systemctl >/dev/null 2>&1; then
|
||||
# `systemctl cat` تنها بررسیِ قابلِ اتکاست: list-unit-files حتی وقتی چیزی
|
||||
# پیدا نکند هم کدِ ۰ برمیگرداند.
|
||||
for candidate in tadrisino tadrisino-api mathapp gunicorn; do
|
||||
# عمداً نامِ عامِ `gunicorn` در این فهرست نیست. روی سرورِ واقعی چند اپِ
|
||||
# مختلف کنارِ هم هستند و یک `gunicorn.service` وجود دارد که مالِ تیمِ
|
||||
# دیگری است — حدس زدنِ آن یعنی ریاستارت کردنِ سرویسِ یک نفرِ دیگر. اگر
|
||||
# نامِ سرویس در این فهرست نبود، TADRISINO_SERVICE را صریح بدهید.
|
||||
for candidate in tadrisino tadrisino-api gunicorn-mathapp mathapp; do
|
||||
if systemctl cat "${candidate}.service" >/dev/null 2>&1; then
|
||||
SERVICE="$candidate"; break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
RESTART_OK=0
|
||||
if [ -n "$SERVICE" ]; then
|
||||
# شکستِ ریاستارت نباید اسکریپت را بیصدا تمام کند؛ بررسیِ سلامتِ پایین
|
||||
# همچنان باید اجرا شود تا معلوم شود سرویسِ قبلی هنوز بالاست یا نه.
|
||||
# زمانِ بالا آمدنِ سرویس قبل و بعد مقایسه میشود.
|
||||
#
|
||||
# چرا: قبلاً فقط خروجیِ `systemctl restart` نگاه میشد و بعد سلامت از روی
|
||||
# آدرسِ عمومی چک میشد. ولی وقتی ریاستارت شکست میخورد، پروسهی *قدیمی*
|
||||
# هنوز بالا بود و همان ۲۰۰ را میداد — یعنی اسکریپت «✓ سالم» میگفت در
|
||||
# حالی که کدِ جدید اصلاً بار نشده بود. روی سرور دو روز همینطور ماند: کد و
|
||||
# محتوا و فایلهای استاتیک روی دیسک بودند و هیچکدام سرو نمیشدند.
|
||||
BEFORE="$(systemctl show "$SERVICE" -p ActiveEnterTimestamp --value 2>/dev/null || true)"
|
||||
if sudo systemctl restart "$SERVICE"; then
|
||||
printf ' سرویسِ %s ریاستارت شد\n' "$SERVICE"
|
||||
AFTER="$(systemctl show "$SERVICE" -p ActiveEnterTimestamp --value 2>/dev/null || true)"
|
||||
if [ -n "$BEFORE" ] && [ "$BEFORE" = "$AFTER" ]; then
|
||||
warn "دستورِ ریاستارت خطا نداد ولی سرویس بالا نیامد (هنوز از $BEFORE در حال اجراست).
|
||||
یعنی کدِ جدید بار نشده. لاگ: sudo journalctl -u $SERVICE -n 50 --no-pager"
|
||||
else
|
||||
RESTART_OK=1
|
||||
printf ' سرویسِ %s ریاستارت شد\n' "$SERVICE"
|
||||
fi
|
||||
else
|
||||
warn "ریاستارتِ $SERVICE شکست خورد (شاید sudo رمز میخواهد). خودتان اجرا کنید:
|
||||
sudo systemctl restart $SERVICE"
|
||||
@@ -185,6 +205,12 @@ for attempt in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if [ "$CODE" = "200" ]; then
|
||||
printf '%s✓ سرویس سالم بالا آمد%s (%s)\n' "$C_OK" "$C_OFF" "$url"
|
||||
printf '%s\n' "$BODY" | python -m json.tool 2>/dev/null | sed 's/^/ /' || printf ' %s\n' "$BODY"
|
||||
# ۲۰۰ گرفتن بهتنهایی یعنی «چیزی جواب میدهد»، نه «کدِ جدید بالاست».
|
||||
if [ "$RESTART_OK" != "1" ]; then
|
||||
warn "ولی سرویس ریاستارت نشد — این جوابْ از پروسهی قدیمی است و کدِ
|
||||
جدید هنوز سرو نمیشود. تا ریاستارت نکنید دیپلوی ناتمام است."
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user