Files
security-alert-center/deploy/sac-deploy.sh
T

162 lines
5.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Полное обновление SAC на сервере (native).
# Установка: sudo cp /opt/security-alert-center/deploy/sac-deploy.sh /opt/sac-deploy.sh
# sudo chmod 755 /opt/sac-deploy.sh
# Запуск: sudo /opt/sac-deploy.sh
#
# Выполняет от пользователя sac: git pull, pip, alembic, npm build.
# От root: systemctl restart sac-api.
set -euo pipefail
APP_ROOT="${SAC_APP_ROOT:-/opt/security-alert-center}"
APP_USER="${SAC_APP_USER:-sac}"
SERVICE_NAME="${SAC_SERVICE:-sac-api}"
CONFIG_FILE="${SAC_CONFIG_FILE:-${APP_ROOT}/config/sac-api.env}"
log() { printf '[sac-deploy] %s\n' "$*"; }
die() { printf '[sac-deploy] ERROR: %s\n' "$*" >&2; exit 1; }
if [ "$(id -u)" -ne 0 ]; then
die "Запускайте от root: sudo /opt/sac-deploy.sh"
fi
id "$APP_USER" &>/dev/null || die "Пользователь ${APP_USER} не существует"
if [ ! -d "${APP_ROOT}/.git" ]; then
die "Не найден git-репозиторий: ${APP_ROOT}"
fi
log "Выравнивание владельца ${APP_ROOT}${APP_USER}:${APP_USER}"
chown -R "${APP_USER}:${APP_USER}" "${APP_ROOT}"
log "git fetch + sync"
sudo -u "${APP_USER}" git -C "${APP_ROOT}" fetch --prune
if sudo -u "${APP_USER}" git -C "${APP_ROOT}" pull --ff-only 2>/dev/null; then
log "git: fast-forward OK"
else
UPSTREAM="$(sudo -u "${APP_USER}" git -C "${APP_ROOT}" rev-parse --abbrev-ref '@{u}' 2>/dev/null || true)"
if [ -z "${UPSTREAM}" ]; then
UPSTREAM="origin/main"
fi
log "WARN: fast-forward невозможен (часто после force-push на kalinamall) — reset --hard ${UPSTREAM}"
sudo -u "${APP_USER}" git -C "${APP_ROOT}" reset --hard "${UPSTREAM}"
fi
if [ ! -f "${CONFIG_FILE}" ]; then
die "Нет конфига: ${CONFIG_FILE}"
fi
VENV="${APP_ROOT}/backend/.venv"
if [ ! -x "${VENV}/bin/pip" ]; then
die "Нет venv: ${VENV} — сначала установите по install-ubuntu-24.04-native.md"
fi
log "pip install -r requirements.txt"
sudo -u "${APP_USER}" "${VENV}/bin/pip" install -q -r "${APP_ROOT}/backend/requirements.txt"
log "alembic upgrade head"
sudo -u "${APP_USER}" bash -c "
set -a
# shellcheck source=/dev/null
source '${CONFIG_FILE}'
set +a
cd '${APP_ROOT}/backend' && '${VENV}/bin/alembic' upgrade head
"
if [ -f "${APP_ROOT}/frontend/package.json" ]; then
if ! command -v npm >/dev/null 2>&1; then
log "npm не найден — пропуск сборки UI (apt install nodejs npm)"
else
log "frontend: npm ci / build"
sudo -u "${APP_USER}" bash -c "
cd '${APP_ROOT}/frontend'
if [ -f package-lock.json ]; then npm ci; else npm install; fi
npm run build
"
if [ ! -f "${APP_ROOT}/frontend/dist/index.html" ]; then
die "Сборка UI не создала frontend/dist/index.html"
fi
fi
fi
if [ -f "${APP_ROOT}/deploy/systemd/${SERVICE_NAME}.service" ]; then
SYSTEMD_DST="/etc/systemd/system/${SERVICE_NAME}.service"
if [ ! -f "${SYSTEMD_DST}" ] || ! cmp -s "${APP_ROOT}/deploy/systemd/${SERVICE_NAME}.service" "${SYSTEMD_DST}"; then
log "Обновление systemd unit → ${SYSTEMD_DST}"
cp "${APP_ROOT}/deploy/systemd/${SERVICE_NAME}.service" "${SYSTEMD_DST}"
systemctl daemon-reload
fi
fi
log "Проверка DATABASE_URL (как у uvicorn через SAC_CONFIG_FILE)"
sudo -u "${APP_USER}" bash -c "
export SAC_CONFIG_FILE='${CONFIG_FILE}'
cd '${APP_ROOT}/backend'
'${VENV}/bin/python' -c \"
from sqlalchemy import create_engine, text
from app.config import get_settings
engine = create_engine(get_settings().database_url, pool_pre_ping=True)
with engine.connect() as conn:
conn.execute(text('SELECT 1'))
print('db: OK')
\"
" || die "PostgreSQL: проверьте DATABASE_URL в ${CONFIG_FILE} и systemctl status postgresql"
log "systemctl restart ${SERVICE_NAME}"
systemctl restart "${SERVICE_NAME}"
systemctl is-active --quiet "${SERVICE_NAME}" || die "${SERVICE_NAME} не active"
HEALTH_OK=0
for _ in 1 2 3 4 5 6; do
sleep 2
if curl -sf "http://127.0.0.1:8000/health" >/dev/null 2>&1; then
HEALTH_OK=1
break
fi
done
if [ "${HEALTH_OK}" -eq 1 ]; then
log "health: OK (http://127.0.0.1:8000/health)"
else
die "${SERVICE_NAME} запущен, но /health не ответил — journalctl -u ${SERVICE_NAME} -n 80 --no-pager"
fi
RENDER_DAILY_TIMER="${APP_ROOT}/deploy/systemd/render-sac-daily-report-timer.sh"
if [ -f "${RENDER_DAILY_TIMER}" ]; then
chmod +x "${RENDER_DAILY_TIMER}" 2>/dev/null || true
fi
for aux in sac-retention sac-daily-report; do
for suffix in service timer; do
src="${APP_ROOT}/deploy/systemd/${aux}.${suffix}"
dst="/etc/systemd/system/${aux}.${suffix}"
if [ "${aux}" = "sac-daily-report" ] && [ "${suffix}" = "timer" ]; then
if [ -x "${RENDER_DAILY_TIMER}" ]; then
log "Генерация ${dst} из ${CONFIG_FILE} (SAC_DAILY_REPORT_HOUR/TIMEZONE)"
bash "${RENDER_DAILY_TIMER}" "${CONFIG_FILE}" "${dst}"
systemctl daemon-reload
systemctl restart "${aux}.timer" 2>/dev/null || systemctl start "${aux}.timer" 2>/dev/null || true
elif [ -f "${src}" ]; then
log "WARN: ${RENDER_DAILY_TIMER} не найден — копируем статический timer"
cp "${src}" "${dst}"
systemctl daemon-reload
fi
continue
fi
if [ -f "${src}" ]; then
if [ ! -f "${dst}" ] || ! cmp -s "${src}" "${dst}"; then
log "Обновление ${dst}"
cp "${src}" "${dst}"
systemctl daemon-reload
fi
fi
done
if [ -f "/etc/systemd/system/${aux}.timer" ]; then
systemctl enable "${aux}.timer" 2>/dev/null || true
systemctl start "${aux}.timer" 2>/dev/null || true
fi
done
log "Готово."