let a deploy repair the server instead of stopping at it
تا حالا اگر کسی روی سرور فایلی را دستی عوض کرده بود، `git pull --ff-only` شکست میخورد و کلِ اسکریپت همانجا میایستاد. چون هیچکدام از مراحلِ بعدی اجرا نمیشد، سرور با کدِ قدیمی میماند — بیصدا. یک بار همین دو روز طول کشید. حالا مرحلهی اول fetch میکند، اگر تغییرِ دستی (یا کامیتِ محلی) باشد آن را در .deploy-backups/*.patch نگه میدارد، و با `git reset --hard origin/<branch>` کنارش میگذارد و ادامه میدهد. سرور در هر وضعیتی باشد، یک اجرا دقیقاً همان چیزی میشود که روی gitea است. `git clean` عمداً زده نمیشود و نباید اضافه شود: db.sqlite3 و .env و .django_secret_key ردیابینشده و داخلِ همین پوشهاند. با مخزنِ ساختگی هر سه حالت آزموده شد: تغییرِ دستی، درختِ تمیز، و کامیتِ محلیِ واگرا. در هر سه، .env و db.sqlite3 دستنخورده ماندند. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
34
deploy.sh
34
deploy.sh
@@ -42,9 +42,39 @@ fi
|
||||
# ─── ۱. کدِ تازه ────────────────────────────────────────────────────────────
|
||||
if [ "${SKIP_PULL:-0}" != "1" ]; then
|
||||
step "گرفتنِ کدِ تازه"
|
||||
# امضای خودِ این فایل قبل از pull. توضیحش پایینتر.
|
||||
# امضای خودِ این فایل قبل از بهروزرسانی. توضیحش پایینتر.
|
||||
SELF_BEFORE="$(cksum "$0" 2>/dev/null || true)"
|
||||
git pull --ff-only || fail "git pull نشد. اگر تغییرِ محلی دارید اول تعیین تکلیفش کنید."
|
||||
|
||||
# شاخهی فعلی؛ اگر HEAD جدا افتاده باشد main مبنا میشود.
|
||||
BRANCH="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo main)"
|
||||
[ "$BRANCH" = "HEAD" ] && BRANCH=main
|
||||
|
||||
git fetch origin "$BRANCH" \
|
||||
|| fail "به gitea وصل نشد. شبکه یا دسترسیِ مخزن را بررسی کنید."
|
||||
|
||||
# اگر کسی روی سرور فایلی را دستی عوض کرده، اول نسخهی پشتیبان، بعد کنار
|
||||
# گذاشتنش.
|
||||
#
|
||||
# چرا خودکار و نه توقف: قبلاً اینجا `git pull --ff-only` بود و با هر تغییرِ
|
||||
# دستی کلِ دیپلوی همانجا میایستاد — و چون بقیهی مراحل اجرا نمیشد، سرور
|
||||
# با کدِ قدیمی میماند بدونِ اینکه کسی بفهمد. دقیقاً همین یک بار دو روز طول
|
||||
# کشید. حالا تغییرِ دستی مانعِ استقرار نیست؛ ذخیره میشود و رد میشویم.
|
||||
if ! git diff --quiet HEAD 2>/dev/null; then
|
||||
mkdir -p .deploy-backups
|
||||
PATCH=".deploy-backups/local-changes-$(date +%Y%m%d-%H%M%S).patch"
|
||||
git diff HEAD > "$PATCH" 2>/dev/null || true
|
||||
warn "روی سرور تغییرِ دستی پیدا شد. در $PATCH ذخیره شد و کنار گذاشته میشود.
|
||||
برای دیدنش: cat $PATCH
|
||||
اگر لازم بود: git apply $PATCH"
|
||||
fi
|
||||
|
||||
# ⚠️ اینجا عمداً `git clean` زده نمیشود و هرگز هم نباید زده شود:
|
||||
# db.sqlite3 و .env و .django_secret_key هیچکدام در گیت نیستند و داخلِ همین
|
||||
# پوشهاند. یک `git clean -fd` یعنی نابودیِ دیتابیس، تنظیمات، و کلیدی که
|
||||
# همهی نشستهای ورود با آن امضا شدهاند. reset --hard فقط فایلهای ردیابیشده
|
||||
# را برمیگرداند و به اینها کار ندارد.
|
||||
git reset --hard "origin/$BRANCH" \
|
||||
|| fail "برگرداندن به origin/$BRANCH نشد؛ هیچ تغییری اعمال نشد."
|
||||
|
||||
# اگر همین اسکریپت در pull عوض شد، نسخهی تازه از اول اجرا میشود.
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user