diff --git a/README.md b/README.md index 4a29498..811f628 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,8 @@ npm run dev # переменные из `.dev_env` Сервер: `http://127.0.0.1:3333`. Проверка: `GET /health`. -Черновик деплоя на Proxmox: [docs/test-deploy-proxmox.md](docs/test-deploy-proxmox.md). +Черновик деплоя на Proxmox: [docs/test-deploy-proxmox.md](docs/test-deploy-proxmox.md). +Обновление уже развёрнутого стенда: [docs/deploy-changes.md](docs/deploy-changes.md). ### Фронтенд diff --git a/docs/deploy-changes.md b/docs/deploy-changes.md new file mode 100644 index 0000000..abb8fa3 --- /dev/null +++ b/docs/deploy-changes.md @@ -0,0 +1,100 @@ +# Справка: как задеплоить изменения + +Как обновить уже работающий стенд (код на сервере + фронт в nginx) после правок в репозитории. + +## 1. Перед выкладкой (локально, по желанию) + +- **Фронт**: `cd client && npm run lint && npm run build` — убедиться, что сборка проходит. + +### Windows: `npm ci` / сборка падает с EPERM на `.node` + +Часто файл держит **запущенный `npm run dev`** (Vite), другой терминал с Node или антивирус. Сделайте: + +1. Остановить все dev-серверы и лишние процессы `node`. +2. Запускать деплой из **Git Bash** или через **`.\scripts\deploy-ssh.ps1`** (не вызывайте `deploy-ssh.sh` напрямую из PowerShell без `bash`). +3. Повторить `./scripts/deploy-ssh.sh` (скрипт перед `npm ci` удаляет каталоги `@unrs` и `@rolldown` в `client/node_modules`, если EPERM из‑за блокировок). +4. Если не помогло: вручную `cd client && npm run build`, затем **`./scripts/deploy-ssh.sh --frontend-only --skip-build`** (выложится уже готовый `client/dist`). + +- **Бэкенд**: при изменениях в `server/prisma` — миграции должны быть в репозитории; на сервере выполнится `prisma migrate deploy` (см. скрипт деплоя). + +## 2. Переменные окружения на сервере + +После обновления кода сверьте `server/.env` с актуальным **`server/.env.example`** на предмет новых переменных. + +Актуально для загрузок файлов (если нужны нестандартные лимиты): + +- `PRODUCT_IMAGE_MAX_FILE_BYTES` — фото товаров в админке (по умолчанию 20 МБ). +- `OTHER_UPLOAD_MAX_FILE_BYTES` — отзывы, чек оплаты и т.п. (по умолчанию 2 МБ). +- `MAX_UPLOAD_BODY_BYTES` — весь POST multipart (по умолчанию рассчитывается от лимита фото товара × 10 + запас). + +Общие для публикации: `JWT_SECRET`, `ADMIN_EMAIL`, `DATABASE_URL`, `CORS_ORIGIN`, при раздельных доменах — `VITE_*` на этапе сборки фронта, `SERVER_PUBLIC_URL` / `CLIENT_PUBLIC_URL` для OAuth. + +После правок `.env` **перезапустите API** (systemd или ваша команда). + +## 3. Автоматический деплой по SSH (рекомендуется) + +1. Скопируйте `scripts/deploy.env.example` в **`scripts/deploy.env`** и заполните: + - `DEPLOY_HOST`, `DEPLOY_USER`, `DEPLOY_PATH`, `DEPLOY_FRONTEND_DIST`; + - при необходимости `DEPLOY_SSH_IDENTITY`, `DEPLOY_RESTART_CMD` (например `systemctl restart craftshop-api`). +2. Из корня репозитория (нужен **bash**: Git Bash / WSL / Linux/macOS): + + ```bash + ./scripts/deploy-ssh.sh --all + ``` + + Варианты: + + - `--frontend-only` / `-f` — только сборка `client` и выкладка `dist` на сервер. + - `--backend-only` / `-b` — только `server` (rsync, `npm ci`, Prisma migrate), плюс `DEPLOY_RESTART_CMD` если задан. + - `--all` / `-a` — и фронт, и бэкенд (поведение по умолчанию). + +3. Убедитесь, что после бэкенд-части API перезапущен (`DEPLOY_RESTART_CMD` или вручную). + +Подробности опций: в начале файла **`scripts/deploy-ssh.sh`** (справка `usage`). + +## 4. Первичный деплой с нуля (LAN / один раз) + +Если сервер ещё не настроен, используйте сценарий первичной подготовки (bootstrap, systemd, первый выклад): + +- **`scripts/complete-lan-deploy.ps1`** (Windows) — нужны `scripts/deploy.env` и `scripts/craftshop-remote-lan.env`, см. комментарии в скрипте. + +Черновик архитектуры и требований к ВМ: **[docs/test-deploy-proxmox.md](test-deploy-proxmox.md)**. + +## 5. Ручное обновление (если без скрипта) + +**Бэкенд** (на сервере, в каталоге приложения, например `/opt/craftshop/server`): + +```bash +git pull +npm ci +npx prisma migrate deploy +# при необходимости: npx prisma db seed +``` + +Перезапуск процесса Node (пример): + +```bash +systemctl restart craftshop-api +``` + +**Фронт** (на машине разработчика): + +```bash +cd client +npm ci +npm run build +``` + +Содержимое **`client/dist/`** скопируйте в каталог статики nginx (как у вас настроено, часто совпадает с `DEPLOY_FRONTEND_DIST` из `deploy.env.example`). + +## 6. Что не потерять при деплое + +- Файл **SQLite** и каталог **`server/uploads/`** должны лежать на **персистентном диске** (не внутри временного слоя контейнера без тома). +- Nginx (или аналог): **`/api`** → прокси на Fastify, **`/uploads`** → те же файлы, что пишет сервер, либо прокси на `@fastify/static` (см. [test-deploy-proxmox.md](test-deploy-proxmox.md)). + +## 7. Проверка после выкладки + +- `GET https://<ваш-домен>/api/health` или `curl http://127.0.0.1:3333/health` на сервере. +- Открыть витрину, при необходимости войти в админку и проверить загрузку фото (лимиты см. выше). + +Дополнительно: общий обзор проекта и локальный запуск — **[README.md](../README.md)**. diff --git a/scripts/deploy-ssh.ps1 b/scripts/deploy-ssh.ps1 index fb3ac66..9aeb312 100644 --- a/scripts/deploy-ssh.ps1 +++ b/scripts/deploy-ssh.ps1 @@ -32,6 +32,9 @@ function Show-Help { Конфиг: scripts/deploy.env (скопируйте из deploy.env.example). Нужны: bash (Git for Windows) и rsync в PATH. rsync без Git: установите пакет (например, choco install rsync). + +Если npm ci падает с EPERM на .node (Windows): остановите Vite/Node, затем снова .\scripts\deploy-ssh.ps1 +Или: cd client; npm run build; затем .\scripts\deploy-ssh.ps1 -SkipBuild (только выкладка dist). "@ | Write-Host } diff --git a/scripts/deploy-ssh.sh b/scripts/deploy-ssh.sh index f83cb07..a32460d 100644 --- a/scripts/deploy-ssh.sh +++ b/scripts/deploy-ssh.sh @@ -178,8 +178,9 @@ deploy_frontend() { echo ">>> Фронт: npm ci и npm run build (локально)" # Windows: ESLint/typescript-eslint тянут @unrs/*.node — npm ci часто получает EPERM unlink, если файл держит Node/IDE или остался мусор .resolver-binding-* после сбоя. if should_use_tar_transport; then - echo ">>> (Windows/Git Bash) перед npm ci: удалить client/node_modules/@unrs и мусор .resolver-binding-* (EPERM unlink)" - rm -rf "$ROOT/client/node_modules/@unrs" 2>/dev/null || true + echo ">>> (Windows/Git Bash) перед npm ci: снимаем блокировки нативных .node (@unrs, @rolldown, .resolver-binding-*)" + echo ">>> Подсказка: остановите «npm run dev» / dev-серверы и IDE, если EPERM останется." + rm -rf "$ROOT/client/node_modules/@unrs" "$ROOT/client/node_modules/@rolldown" 2>/dev/null || true ( cd "$ROOT/client/node_modules" 2>/dev/null || exit 0 shopt -s nullglob @@ -188,7 +189,12 @@ deploy_frontend() { done ) fi - (cd "$ROOT/client" && npm ci && npm run build) + (cd "$ROOT/client" && npm ci && npm run build) || { + echo "" >&2 + echo "Сборка фронта не удалась. На Windows часто EPERM на .node — закройте процессы Node (dev-сервер), повторите." >&2 + echo "Или соберите фронт вручную (cd client && npm run build), затем: $0 --frontend-only --skip-build" >&2 + exit 1 + } else echo ">>> Фронт: сборка пропущена (--skip-build)" if [[ ! -d "$ROOT/client/dist" ]]; then