feat(deploy): переключить .env на проде на Infisical вместо ручного файла
deploy.sh теперь на каждом запуске логинится в Infisical (Machine Identity Universal Auth) и генерирует .env из окружения prod перед синком кода и поднятием контейнеров. Если Infisical недоступен или вернул подозрительно мало ключей — деплой падает раньше, не трогая рабочий .env на сервере. Добавлен шаг compose up -d без --build для всех бэкенд-сервисов после сборки изменившихся — иначе правка секрета без изменения кода не попадала бы в уже запущенные контейнеры (docker compose пересоздаёт только то, чей эффективный конфиг реально изменился, остальное не трогает).
This commit is contained in:
@@ -5,7 +5,10 @@
|
||||
# Запускается Gitea Actions runner'ом в host-режиме прямо на app-хосте 1.32
|
||||
# (см. .gitea/workflows/deploy.yml). Ожидает:
|
||||
# - cwd = ПОЛНЫЙ чекаут репозитория (нужен git-лог для diff);
|
||||
# - переменную PVE_PASSWORD (секрет) для доступа к Proxmox-хосту → CT 102.
|
||||
# - переменную PVE_PASSWORD (секрет) для доступа к Proxmox-хосту → CT 102;
|
||||
# - INFISICAL_CLIENT_ID / INFISICAL_CLIENT_SECRET (Machine Identity
|
||||
# "claude-ai", Universal Auth) — .env на проде теперь генерируется из
|
||||
# Infisical (prod) на каждом деплое, а не правится руками на сервере.
|
||||
#
|
||||
# Пересобирается только то, чей код изменился с прошлого деплоя (маркер SHA в
|
||||
# $APP/.last_deploy_sha). Это критично: worker-gpu тянет torch/faiss (~2 ГБ),
|
||||
@@ -51,7 +54,41 @@ else
|
||||
fi
|
||||
REBUILD="$(echo "$REBUILD" | xargs || true)"
|
||||
|
||||
echo "==> [1/5] Синхронизация кода в $APP (сохраняя .env и compose)"
|
||||
echo "==> [1/6] Секреты из Infisical (prod) → .env"
|
||||
INFISICAL_BIN="$APP/.infisical-cli"
|
||||
if [ ! -x "$INFISICAL_BIN" ]; then
|
||||
echo " ставлю infisical CLI (разово)"
|
||||
curl -sSL -o /tmp/infisical-cli.tar.gz \
|
||||
"https://github.com/Infisical/infisical/releases/download/infisical-cli%2Fv0.31.1/infisical_0.31.1_linux_amd64.tar.gz"
|
||||
tar xzf /tmp/infisical-cli.tar.gz -C /tmp infisical
|
||||
mv /tmp/infisical "$INFISICAL_BIN"
|
||||
rm -f /tmp/infisical-cli.tar.gz
|
||||
fi
|
||||
|
||||
INFISICAL_DOMAIN=https://infisical.jze9.ru/api
|
||||
INFISICAL_PROJECT_ID=a2e7505e-573f-43e9-872b-4ed7a6bed7b8
|
||||
INFISICAL_TOKEN="$("$INFISICAL_BIN" login --method=universal-auth \
|
||||
--client-id="${INFISICAL_CLIENT_ID:?INFISICAL_CLIENT_ID не задан}" \
|
||||
--client-secret="${INFISICAL_CLIENT_SECRET:?INFISICAL_CLIENT_SECRET не задан}" \
|
||||
--domain="$INFISICAL_DOMAIN" --plain --silent)"
|
||||
|
||||
TMP_ENV="$(mktemp)"
|
||||
"$INFISICAL_BIN" export --token="$INFISICAL_TOKEN" --domain="$INFISICAL_DOMAIN" \
|
||||
--projectId="$INFISICAL_PROJECT_ID" --env=prod --format=dotenv --expand=false \
|
||||
--silent > "$TMP_ENV"
|
||||
|
||||
# Не затирать рабочий .env, если Infisical вернул мало строк (недоступен/пуст) —
|
||||
# иначе следующий шаг раскатит прод с пустым конфигом.
|
||||
ENV_LINES="$(grep -cE '^[A-Za-z_][A-Za-z0-9_]*=' "$TMP_ENV" || true)"
|
||||
if [ "$ENV_LINES" -lt 20 ]; then
|
||||
echo "ОШИБКА: Infisical export вернул только $ENV_LINES строк (ожидалось ~38) — сервис недоступен или пуст. Деплой прерван, .env на проде не тронут."
|
||||
rm -f "$TMP_ENV"
|
||||
exit 1
|
||||
fi
|
||||
mv "$TMP_ENV" "$APP/.env"
|
||||
echo " OK: $ENV_LINES секретов"
|
||||
|
||||
echo "==> [2/6] Синхронизация кода в $APP (сохраняя .env и compose)"
|
||||
rsync -a \
|
||||
--exclude='__pycache__/' --exclude='*.pyc' --exclude='.pytest_cache/' \
|
||||
--exclude='node_modules/' --exclude='dist/' \
|
||||
@@ -59,25 +96,33 @@ rsync -a \
|
||||
|
||||
cd "$APP"
|
||||
if [ -n "$REBUILD" ]; then
|
||||
echo "==> [2/5] Пересборка и перезапуск: $REBUILD"
|
||||
echo "==> [3/6] Пересборка и перезапуск: $REBUILD"
|
||||
# shellcheck disable=SC2086
|
||||
$COMPOSE up -d --build $REBUILD
|
||||
else
|
||||
echo "==> [2/5] Бэкенд-сервисы не менялись — пропуск сборки"
|
||||
echo "==> [3/6] Бэкенд-сервисы не менялись — пропуск сборки"
|
||||
fi
|
||||
|
||||
echo "==> [3/5] Миграции БД (с ретраем)"
|
||||
# Секреты в .env могли поменяться без изменения кода (правка в Infisical) —
|
||||
# docker compose сам не пересоздаст контейнер, чей env_file изменился, если
|
||||
# просто повторно не позвать up -d. Дёшево и идемпотентно: compose пересоздаёт
|
||||
# только контейнеры с реально изменившимся конфигом, остальные не трогает.
|
||||
echo "==> [4/6] Применение секретов к неизменившимся сервисам (если менялись)"
|
||||
# shellcheck disable=SC2086
|
||||
$COMPOSE up -d $ALL_BACKEND
|
||||
|
||||
echo "==> [5/6] Миграции БД (с ретраем)"
|
||||
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] Сборка фронтенда"
|
||||
echo "==> [6/6] Сборка фронтенда"
|
||||
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)"
|
||||
echo "==> [6/6] Выкладка статики на CT 102 (через $PVE_HOST)"
|
||||
cd "$APP/services/frontend/dist"
|
||||
tar czf /tmp/academic-dist.tgz .
|
||||
export SSHPASS="${PVE_PASSWORD:?PVE_PASSWORD не задан}"
|
||||
@@ -102,7 +147,7 @@ rm -f /tmp/academic-dist.tgz
|
||||
REMOTE
|
||||
rm -f /tmp/academic-dist.tgz
|
||||
else
|
||||
echo "==> [4-5/5] Фронтенд не менялся — пропуск сборки и выкладки"
|
||||
echo "==> [6/6] Фронтенд не менялся — пропуск сборки и выкладки"
|
||||
fi
|
||||
|
||||
echo "$CUR_SHA" > "$MARKER"
|
||||
|
||||
Reference in New Issue
Block a user