ci: пересобирать только изменённые сервисы + полный клон для diff
All checks were successful
Deploy / deploy (push) Successful in 3s
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>
This commit is contained in:
@@ -1,28 +1,55 @@
|
||||
#!/usr/bin/env bash
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Деплой anti-plagiarism.
|
||||
# Деплой anti-plagiarism (умная пересборка — только изменённых сервисов).
|
||||
#
|
||||
# Запускается Gitea Actions runner'ом в host-режиме прямо на app-хосте 1.32
|
||||
# (см. .gitea/workflows/deploy.yml). Ожидает:
|
||||
# - cwd = свежий чекаут репозитория;
|
||||
# - переменную окружения PVE_PASSWORD (секрет Gitea) для доступа к Proxmox-хосту,
|
||||
# через который статика кладётся в CT 102 (reverse-proxy nginx).
|
||||
# - cwd = ПОЛНЫЙ чекаут репозитория (нужен git-лог для diff);
|
||||
# - переменную PVE_PASSWORD (секрет) для доступа к Proxmox-хосту → CT 102.
|
||||
#
|
||||
# Что делает:
|
||||
# 1. Синхронизирует код (services/ + scripts/) в /home/user/anti-plagiarism,
|
||||
# НЕ трогая .env и локально-правленый docker-compose.prod.yml.
|
||||
# 2. Пересобирает и перезапускает бэкенд-сервисы (api + воркеры).
|
||||
# 3. Применяет миграции БД.
|
||||
# 4. Собирает фронтенд (npm build) в статику.
|
||||
# 5. Выкладывает статику в /var/www/academic на CT 102 (с бэкапом + reload nginx).
|
||||
# Пересобирается только то, чей код изменился с прошлого деплоя (маркер 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 # Proxmox-хост, через pct exec которого живёт CT 102
|
||||
PVE_HOST=192.168.20.254
|
||||
COMPOSE="docker compose -f docker-compose.prod.yml"
|
||||
BACKEND_SERVICES="api worker-gpu worker-indexer worker-notifier worker-gost"
|
||||
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 \
|
||||
@@ -30,33 +57,35 @@ rsync -a \
|
||||
--exclude='node_modules/' --exclude='dist/' \
|
||||
"$SRC/services" "$SRC/scripts" "$APP/"
|
||||
|
||||
echo "==> [2/5] Пересборка и перезапуск бэкенд-сервисов"
|
||||
cd "$APP"
|
||||
# shellcheck disable=SC2086
|
||||
$COMPOSE up -d --build $BACKEND_SERVICES
|
||||
if [ -n "$REBUILD" ]; then
|
||||
echo "==> [2/5] Пересборка и перезапуск: $REBUILD"
|
||||
# shellcheck disable=SC2086
|
||||
$COMPOSE up -d --build $REBUILD
|
||||
else
|
||||
echo "==> [2/5] Бэкенд-сервисы не менялись — пропуск сборки"
|
||||
fi
|
||||
|
||||
echo "==> [3/5] Миграции БД (с ретраем, пока api поднимается)"
|
||||
echo "==> [3/5] Миграции БД (с ретраем)"
|
||||
for i in $(seq 1 10); do
|
||||
if $COMPOSE exec -T api alembic upgrade head; then
|
||||
break
|
||||
fi
|
||||
echo " api ещё не готов, повтор $i/10..."
|
||||
sleep 5
|
||||
$COMPOSE exec -T api alembic upgrade head && break
|
||||
echo " api ещё не готов, повтор $i/10..."; sleep 5
|
||||
done
|
||||
|
||||
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"
|
||||
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'
|
||||
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 '
|
||||
@@ -71,6 +100,10 @@ nginx -t && nginx -s reload
|
||||
'
|
||||
rm -f /tmp/academic-dist.tgz
|
||||
REMOTE
|
||||
rm -f /tmp/academic-dist.tgz
|
||||
rm -f /tmp/academic-dist.tgz
|
||||
else
|
||||
echo "==> [4-5/5] Фронтенд не менялся — пропуск сборки и выкладки"
|
||||
fi
|
||||
|
||||
echo "==> Деплой завершён успешно"
|
||||
echo "$CUR_SHA" > "$MARKER"
|
||||
echo "==> Деплой завершён успешно (маркер обновлён: $CUR_SHA)"
|
||||
|
||||
Reference in New Issue
Block a user