All checks were successful
Deploy / deploy (push) Successful in 3s
Первый прогон вслепую пересобирал все 5 бэкенд-образов, включая worker-gpu (torch/faiss ~2 ГБ) — на медленном канале это ~1-2 часа впустую, хотя коммит менял только CI-файлы. Теперь deploy.sh по git-diff с прошлого деплоя (маркер .last_deploy_sha) собирает лишь сервисы с изменённым кодом; фронт пересобирается только при правках services/frontend; правка compose = полная пересборка. Workflow клонирует репозиторий полностью (нужен лог для diff). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
110 lines
4.8 KiB
Bash
Executable File
110 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
# Деплой anti-plagiarism (умная пересборка — только изменённых сервисов).
|
||
#
|
||
# Запускается Gitea Actions runner'ом в host-режиме прямо на app-хосте 1.32
|
||
# (см. .gitea/workflows/deploy.yml). Ожидает:
|
||
# - cwd = ПОЛНЫЙ чекаут репозитория (нужен git-лог для diff);
|
||
# - переменную PVE_PASSWORD (секрет) для доступа к Proxmox-хосту → CT 102.
|
||
#
|
||
# Пересобирается только то, чей код изменился с прошлого деплоя (маркер SHA в
|
||
# $APP/.last_deploy_sha). Это критично: worker-gpu тянет torch/faiss (~2 ГБ),
|
||
# его нельзя пересобирать без нужды. Если менялся docker-compose.prod.yml —
|
||
# пересобираются все бэкенд-сервисы.
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
set -euo pipefail
|
||
|
||
APP=/home/user/anti-plagiarism
|
||
SRC="$(pwd)"
|
||
PVE_HOST=192.168.20.254
|
||
COMPOSE="docker compose -f docker-compose.prod.yml"
|
||
ALL_BACKEND="api worker-gpu worker-indexer worker-notifier worker-gost"
|
||
MARKER="$APP/.last_deploy_sha"
|
||
|
||
CUR_SHA="$(git -C "$SRC" rev-parse HEAD)"
|
||
|
||
# ── Определить, что менялось ──────────────────────────────────────────────────
|
||
FULL=0
|
||
CHANGED=""
|
||
if [ -f "$MARKER" ] && PREV="$(cat "$MARKER")" && [ -n "$PREV" ] \
|
||
&& git -C "$SRC" cat-file -e "$PREV" 2>/dev/null; then
|
||
CHANGED="$(git -C "$SRC" diff --name-only "$PREV" "$CUR_SHA")"
|
||
echo "Изменения с $PREV:"
|
||
echo "$CHANGED" | sed 's/^/ /'
|
||
# Правка общего compose затрагивает все образы
|
||
echo "$CHANGED" | grep -qE '^docker-compose\.prod\.yml$' && FULL=1
|
||
else
|
||
echo "Маркер прошлого деплоя недоступен — полная пересборка (разовая)"
|
||
FULL=1
|
||
fi
|
||
|
||
REBUILD=""
|
||
FRONTEND_CHANGED=0
|
||
if [ "$FULL" = 1 ]; then
|
||
REBUILD="$ALL_BACKEND"
|
||
FRONTEND_CHANGED=1
|
||
else
|
||
for svc in $ALL_BACKEND; do
|
||
echo "$CHANGED" | grep -qE "^services/$svc/" && REBUILD="$REBUILD $svc"
|
||
done
|
||
echo "$CHANGED" | grep -qE '^services/frontend/' && FRONTEND_CHANGED=1
|
||
fi
|
||
REBUILD="$(echo "$REBUILD" | xargs || true)"
|
||
|
||
echo "==> [1/5] Синхронизация кода в $APP (сохраняя .env и compose)"
|
||
rsync -a \
|
||
--exclude='__pycache__/' --exclude='*.pyc' --exclude='.pytest_cache/' \
|
||
--exclude='node_modules/' --exclude='dist/' \
|
||
"$SRC/services" "$SRC/scripts" "$APP/"
|
||
|
||
cd "$APP"
|
||
if [ -n "$REBUILD" ]; then
|
||
echo "==> [2/5] Пересборка и перезапуск: $REBUILD"
|
||
# shellcheck disable=SC2086
|
||
$COMPOSE up -d --build $REBUILD
|
||
else
|
||
echo "==> [2/5] Бэкенд-сервисы не менялись — пропуск сборки"
|
||
fi
|
||
|
||
echo "==> [3/5] Миграции БД (с ретраем)"
|
||
for i in $(seq 1 10); do
|
||
$COMPOSE exec -T api alembic upgrade head && break
|
||
echo " api ещё не готов, повтор $i/10..."; sleep 5
|
||
done
|
||
|
||
if [ "$FRONTEND_CHANGED" = 1 ]; then
|
||
echo "==> [4/5] Сборка фронтенда"
|
||
docker run --rm -v "$APP/services/frontend":/app -w /app node:20-slim \
|
||
sh -c "npm install --no-audit --no-fund --loglevel=error && npm run build"
|
||
|
||
echo "==> [5/5] Выкладка статики на CT 102 (через $PVE_HOST)"
|
||
cd "$APP/services/frontend/dist"
|
||
tar czf /tmp/academic-dist.tgz .
|
||
export SSHPASS="${PVE_PASSWORD:?PVE_PASSWORD не задан}"
|
||
SSHOPT="-o StrictHostKeyChecking=no -o ConnectTimeout=10"
|
||
# shellcheck disable=SC2086
|
||
sshpass -e scp $SSHOPT /tmp/academic-dist.tgz "root@${PVE_HOST}:/tmp/academic-dist.tgz"
|
||
# shellcheck disable=SC2086
|
||
sshpass -e ssh $SSHOPT "root@${PVE_HOST}" 'bash -s' <<'REMOTE'
|
||
set -e
|
||
pct push 102 /tmp/academic-dist.tgz /tmp/academic-dist.tgz
|
||
pct exec 102 -- bash -c '
|
||
set -e
|
||
cd /var/www
|
||
cp -a academic "academic.bak.$(date +%s)"
|
||
cd academic
|
||
rm -rf assets index.html
|
||
tar xzf /tmp/academic-dist.tgz
|
||
chown -R 1000:1000 .
|
||
nginx -t && nginx -s reload
|
||
'
|
||
rm -f /tmp/academic-dist.tgz
|
||
REMOTE
|
||
rm -f /tmp/academic-dist.tgz
|
||
else
|
||
echo "==> [4-5/5] Фронтенд не менялся — пропуск сборки и выкладки"
|
||
fi
|
||
|
||
echo "$CUR_SHA" > "$MARKER"
|
||
echo "==> Деплой завершён успешно (маркер обновлён: $CUR_SHA)"
|