Files
ForbiddenStarsApp/run.sh
T
NotBigGhostandClaude Opus 5 ec1e94119c Чистка: устаревшие комментарии и подсказки, export-скрипт, мусорный файл
Комментарии про методы входа приведены к факту (логин/пароль и Telegram везде,
stub только в development): config.py, .env.example, telegram.py, dev_stub.py,
dev_auth.py, login.py. admin_login.py больше не обещает «строже игроцкого» —
описаны реальные лимиты; client_ip — адрес за прокси уже даёт uvicorn.

Подсказки деплоя: run.ps1/run.sh (build-push на ПК, `up -d` на Pi), compose,
.env.example (build-push.ps1), Caddyfile (туннель-контейнер вместо autossh);
ratelimit.py ссылается на core/events.py вместо CLAUDE.md.

Удалены неиспользуемые scripts/export-prod.sh (с блоком export-ignore в
.gitattributes и упоминаниями в README), db/init_db.py и случайно закоммиченный
файл «h -u origin dev…». #70

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
2026-09-19 03:12:16 +03:00

96 lines
5.8 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
# ╔═══════════════════════════════════════════════════════════════════════════╗
# ║ Единый лаунчер dev. Что запускать — решает APP_ENV из корневого .env ║
# ╚═══════════════════════════════════════════════════════════════════════════╝
# development → uvicorn --reload (бэк) + vite (фронт), нативно (Ctrl+C останавливает оба)
# production → лаунчером НЕ запускается (прод обособлен: docker compose up -d на Pi)
#
# LOCAL_PUBLIC=vps поднимает SSH-туннель на VPS → https://forbidden-stars.ru
# Прод выставляет себя сам через туннель-контейнер (см. docker-compose.yml).
#
# Запуск: ./run.sh (при необходимости: chmod +x run.sh)
set -euo pipefail
root="$(cd "$(dirname "$0")" && pwd)"
envf="$root/.env"
[ -f "$envf" ] || { echo "Нет .env в корне. Скопируйте: cp .env.example .env"; exit 1; }
# Достаём значение ключа из .env (последнее присвоение, без комментариев/пробелов).
env_val() {
grep -E "^[[:space:]]*$1[[:space:]]*=" "$envf" | tail -n1 \
| sed -E 's/^[^=]*=[[:space:]]*//; s/[[:space:]#].*$//'
}
app_env="$(env_val APP_ENV | tr 'A-Z' 'a-z')"; app_env="${app_env:-development}"
local_public="$(env_val LOCAL_PUBLIC | tr 'A-Z' 'a-z')"; local_public="${local_public:-local}"
vps_host="$(env_val VPS_TUNNEL_HOST)"
vps_user="$(env_val VPS_TUNNEL_USER)"; vps_user="${vps_user:-tunnel}"
vps_port="$(env_val VPS_TUNNEL_PORT)"; vps_port="${vps_port:-9001}"
echo "APP_ENV = $app_env LOCAL_PUBLIC = $local_public"
# Поднимает SSH reverse-tunnel в фоне: VPS:$vps_port → localhost:$1 (если LOCAL_PUBLIC=vps).
start_tunnel() {
local local_port="$1"
if [ -z "$vps_host" ]; then
echo "LOCAL_PUBLIC=vps, но VPS_TUNNEL_HOST не задан — туннель пропущен."; return
fi
echo "SSH-туннель: forbidden-stars.ru (VPS:$vps_port) → localhost:$local_port …"
ssh -N -R "${vps_port}:localhost:${local_port}" \
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes \
"${vps_user}@${vps_host}" &
tunnel=$!
trap 'kill "$tunnel" 2>/dev/null || true' EXIT INT TERM
echo " Публично: https://forbidden-stars.ru"
}
case "$app_env" in
development)
py="$root/backend/.venv/bin/python"
[ -x "$py" ] || py="$root/backend/.venv/Scripts/python.exe" # Git Bash на Windows
[ -x "$py" ] || { echo "Нет venv. Сначала: cd backend && python -m venv .venv && pip install -e '.[dev]'"; exit 1; }
[ -d "$root/frontend/node_modules" ] || { echo "Нет node_modules. Сначала: cd frontend && npm install"; exit 1; }
# Сначала схема: ветка могла принести миграцию, и без неё бэк поднимется на
# старой схеме и упадёт 500 на первом же обращении к новой таблице.
echo "Применяю миграции (alembic upgrade head)…"
mig_log="$( cd "$root/backend" && "$py" -m alembic upgrade head 2>&1 )" && mig_code=0 || mig_code=$?
if [ "$mig_code" -ne 0 ]; then
echo "$mig_log"
case "$mig_log" in
*"locate revision"*)
# В базе миграция, которой нет в этой ветке (вернулись с ветки задачи).
# Лишние таблицы старому коду не мешают — продолжаем запуск.
echo "База новее ветки — миграции пропущены." ;;
*)
echo "Миграции не применились — не запускаю. Исправьте ошибку выше и повторите."
exit 1 ;;
esac
fi
echo "Запуск бэка (uvicorn --reload) и фронта (vite)… Ctrl+C — остановить всё."
# --timeout-graceful-shutdown: открытая вкладка держит SSE-поток /api/events вечно, а при
# reload старый процесс ждёт закрытия ВСЕХ соединений — без лимита перезапуск не
# завершается, и сайт висит на загрузке без единой ошибки в логе.
( cd "$root/backend" && exec "$py" -m uvicorn app.main:app --reload --timeout-graceful-shutdown 2 ) &
back=$!
trap 'kill "$back" 2>/dev/null || true' EXIT INT TERM
echo " Бэк: http://127.0.0.1:8000 (Swagger: /api/docs)"
echo " Фронт: http://127.0.0.1:5173"
if [ "$local_public" = "vps" ]; then
start_tunnel 5173
echo " ВНИМАНИЕ: dev опубликован. Любой посетитель может войти по нику без пароля,"
echo " смотреть и создавать игроков, жёстко удалять аккаунты и читать Swagger."
echo " Не держите в dev-базе копию прод-данных."
fi
( cd "$root/frontend" && npm run dev )
;;
production)
echo "production лаунчером не запускается — прод обособлен."
echo "Деплой: на ПК (ветка main) scripts/build-push.sh, затем на Pi: docker compose up -d"
exit 1
;;
*)
echo "Неизвестный APP_ENV='$app_env'. Допустимо: development | production."
exit 1
;;
esac