diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 0ce4272..81ef740 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -16,12 +16,12 @@ jobs: deploy: runs-on: deploy steps: - - name: Клонировать текущий коммит + - name: Клонировать репозиторий (полностью — нужен git-лог для diff) run: | set -euo pipefail SRC="$(mktemp -d)" echo "SRC=$SRC" >> "$GITHUB_ENV" - git clone --depth 1 --branch main \ + git clone --branch main \ https://gitea.jze9.ru/jze9/anti-plagiarism.git "$SRC" - name: Деплой (бэкенд 1.32 + фронтенд CT 102) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 8d9f08c..74aeb98 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -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)"