forked from Tadrisino/MathApp_frontend
67 lines
3.8 KiB
Bash
Executable File
67 lines
3.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# انتشارِ فرانت روی سرور: گرفتنِ کدِ تازه، build، و جابهجاییِ بیوقفهی dist.
|
||
#
|
||
# ./deploy.sh # شاخهی main
|
||
# ./deploy.sh <branch>
|
||
#
|
||
# build در dist.next ساخته میشود و فقط اگر کامل موفق شد جای dist را میگیرد؛
|
||
# پس سایت حتی چند ثانیه هم بیفایل نمیماند. buildِ قبلی در dist.prev میماند:
|
||
# برگشت: rm -rf dist && mv dist.prev dist
|
||
#
|
||
# dist/config.js (آدرسِ API در زمانِ اجرا) اگر روی سرور دستی ویرایش شده باشد،
|
||
# به buildِ تازه منتقل میشود تا با هر انتشار از دست نرود.
|
||
set -euo pipefail
|
||
cd "$(dirname "$0")"
|
||
|
||
BRANCH="${1:-main}"
|
||
step() { printf '\n\033[0;32m▸ %s\033[0m\n' "$1"; }
|
||
fail() { printf '\033[0;31m✖ %s\033[0m\n' "$1" >&2; exit 1; }
|
||
|
||
step "گرفتنِ کدِ تازه ($BRANCH)"
|
||
# DEPLOY_BUNDLE=/مسیر/فایل.bundle: کد از یک git bundle، نه از gitea (مثلِ deploy.shِ بکاند): برای وقتی که سرور
|
||
# به gitea نمیرسد یا اعتبارنامه ندارد. فقط وقتی صریحاً داده شود؛ بیآن نرسیدن به gitea دیپلو را میایستاند.
|
||
if [ -n "${DEPLOY_BUNDLE:-}" ]; then
|
||
[ -f "$DEPLOY_BUNDLE" ] || fail "DEPLOY_BUNDLE=$DEPLOY_BUNDLE وجود ندارد."
|
||
git bundle verify "$DEPLOY_BUNDLE" >/dev/null 2>&1 || fail "bundle معتبر نیست یا کامیتِ پایهاش اینجا نیست."
|
||
git fetch "$DEPLOY_BUNDLE" "$BRANCH:refs/remotes/origin/$BRANCH" || fail "گرفتن از bundle نشد."
|
||
else
|
||
git fetch origin "$BRANCH" || fail "به gitea وصل نشد (اگر فقط از این سرور: DEPLOY_BUNDLE، بالای همین خط)."
|
||
fi
|
||
printf ' origin/%s = %s\n' "$BRANCH" "$(git rev-parse --short "origin/$BRANCH")"
|
||
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
|
||
mkdir -p .deploy-backups
|
||
PATCH=".deploy-backups/local-changes-$(date +%Y%m%d-%H%M%S).patch"
|
||
git diff > "$PATCH"
|
||
printf ' تغییرِ دستی روی سرور بود؛ در %s ذخیره شد.\n' "$PATCH"
|
||
fi
|
||
git reset --hard "origin/$BRANCH"
|
||
git log --oneline -1
|
||
|
||
step "نصبِ وابستگیها"
|
||
npm ci --no-audit --no-fund
|
||
|
||
step "type-check و build"
|
||
rm -rf dist.next
|
||
npx tsc --noEmit || fail "type-check شکست خورد؛ سایت دست نخورد."
|
||
npx vite build --outDir dist.next --emptyOutDir || fail "build شکست خورد؛ سایت دست نخورد."
|
||
|
||
if [ -f dist/config.js ] && ! cmp -s dist/config.js public/config.js; then
|
||
cp dist/config.js dist.next/config.js
|
||
printf ' config.jsِ ویرایششدهی سرور نگه داشته شد.\n'
|
||
fi
|
||
|
||
# فایلهای buildهای قبلی (نامشان hash دارد و با هم برخورد نمیکنند) تا ۳۰ روز میمانند: گوشیای که اپ از قبل
|
||
# در آن باز است هنوز index.htmlِ قبلی را دارد و با باز کردنِ صفحهای که بار نشده همان نامها را میخواهد؛ بیاین
|
||
# ۴۰۴ و صفحهی سفید میگرفت. cp -p زمانِ فایل را نگه میدارد، پس هر فایل ۳۰ روز بعد از buildِ خودش کنار میرود.
|
||
if [ -d dist/assets ]; then
|
||
find dist/assets -type f -mtime -30 -exec cp -p --update=none {} dist.next/assets/ \;
|
||
fi
|
||
|
||
step "جابهجایی"
|
||
rm -rf dist.prev
|
||
[ -d dist ] && mv dist dist.prev
|
||
mv dist.next dist
|
||
API="$(grep -oh 'https\?://[a-zA-Z0-9.-]*/api' dist/assets/*.js | head -1)"
|
||
printf ' منتشر شد. آدرسِ API در build: %s\n' "${API:-(همدامنه /api یا config.js)}"
|
||
printf ' کشِ آروان را برای index.html و config.js پاک کنید اگر تغییری دیده نشد.\n'
|