Files
xboct-deploy/README.md
T

167 lines
7.6 KiB
Markdown
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.
# xboct-deploy
Легковесная CLI-утилита на Rust для централизованного деплоя хобби-проектов
(Node.js, Rust) с локального ПК на слабую VPS по SSH.
- сборка, тесты и линтеры выполняются **локально** — CPU VPS не тратится
- артефакты передаются по **SFTP** (без rsync, работает на Windows/Linux/macOS)
- сервисные команды (`pm2 restart`, `systemctl restart`) запускаются **по SSH**
- fail-fast: упавший шаг немедленно останавливает деплой (ADR-005)
## Установка
```sh
cargo install --path .
```
Требуется Rust 1.88+. Кроссплатформенно: Windows (MSVC), Linux, macOS.
## Быстрый старт
```sh
xboct-deploy --list # показать проекты из конфига
xboct-deploy --list-servers # показать серверы из конфига
xboct-deploy --pick # интерактивно выбрать проект (нечёткий поиск)
xboct-deploy --dry-run demo # напечатать план деплоя без выполнения
xboct-deploy demo # задеплоить проект demo
xboct-deploy --this # задеплоить проект текущей папки (глобальный конфиг)
```
Вывод:
```txt
deploying 'demo'
[Local] running: npm run build... Success! (1.2s)
[SFTP] transferring dist to /var/www/pages... Done! (14 file(s), 231.5 KiB) (829ms)
[Remote] running: pm2 restart pages... Success! (102ms)
Deploy successful! (total 2.3s)
```
## Конфигурация
Файл ищется по цепочке:
1. `--config PATH`, если указан явно;
2. `./deploy.toml` в текущей папке — удобно держать рядом с проектом и в тестах;
3. глобальный `~/.config/xboct-deploy/deploy.toml` — запуск «из любой папки».
`--this` деплоит проект, чей `workdir` совпадает с текущей папкой; конфиг
ищется по обычной цепочке, так что временный локальный `./deploy.toml`
переопределяет глобальный — создали файл, задеплоились, удалили.
Схема — **один проект = один блок**, все параметры точечными ключами:
```toml
[servers.my-vps] # профиль сервера: описывается один раз
host = "195.0.2.10" # алиас из ~/.ssh/config или IP
port = 2222
user = "deploy"
key_path = "~/.ssh/id_ed25519"
base_dir = "/var/www/pages" # корень для относительных sync target
[projects.my-node-app]
server = "my-vps" # ссылка на профиль SSH
workdir = 'C:\code\my-node-app' # где выполнять локальные команды (~ разворачивается)
branch = "main" # опционально: защита от деплоя чужой ветки
env.PUBLIC_BASE_PATH = "/my-node-app" # переменные для локальной сборки
local.commands = ["npm ci", "npm run build"] # шаги сборки на вашей машине
sync = "dist" # залить dist -> <base_dir>/my-node-app
remote.commands = ["pm2 restart pages"] # команды управления по SSH
```
### Поле `sync`
Три формы — выбирай по смыслу:
```toml
sync = "dist" # один источник; target = имя проекта
sync = ["dist", "static"] # несколько источников; target = имя проекта
sync = [{ source = "web/build", target = "/opt/static" }] # полные правила
```
Во всех формах `target` без `/` на конце резолвится через `base_dir` сервера
(`"my-node-app"``/var/www/pages/my-node-app`). Абсолютный target
(`"/opt/static"`) используется как есть. Отдельных блоков `[[...sync]]`,
`[projects.x.env]`, `[projects.x.local]`, `[projects.x.remote]` больше нет —
это не нужно помнить и копировать, всё в блоке проекта.
Проект может задать параметры подключения и напрямую (`host`, `user`, `port`,
`key_path` вместо `server`) — тогда они имеют приоритет над профилем.
Приоритет параметров SSH: проект → `[servers.<name>]``~/.ssh/config` → дефолт.
### Локальные команды после деплоя (`local_after`)
Выполняются на вашей машине **после** sync + remote и **всегда** — и при
успехе, и после любого упавшего шага (deploy всё равно упадёт). Для очистки
артефактов или вебхука с результатом:
```toml
[projects.my-node-app]
server = "my-vps"
workdir = 'C:\code\my-node-app'
local.commands = ["npm run build"]
sync = "dist"
remote.commands = ["pm2 restart pages"]
[projects.my-node-app.local_after]
commands = [
'del /q dist',
'curl -s -X POST https://example.com/hook -d "result=%XD_DEPLOY_RESULT%"',
]
```
Внутри доступны переменные (в cmd — `%VAR%`, в sh — `$VAR`):
- `XD_DEPLOY_RESULT``success` либо `failed`;
- `XD_ERROR` — текст ошибки (только при `failed`).
Эти же переменные доступны в `--dry-run`, где показываются в плане без
выполнения.
### Windows-нюанс TOML
В basic-строках `"..."` бэкслеши — escape-символы, путь `C:\Users` сломает парсинг.
Для путей Windows используйте литеральные строки `'...'`:
```toml
workdir = 'C:\code\my-node-app'
```
или прямые слэши `C:/code/my-node-app`.
## Аутентификация
Цепочка (первый успешный способ используется):
1. **ssh-agent**: OpenSSH-агент (named pipe на Windows / `SSH_AUTH_SOCK` на Unix),
затем Pageant; перебираются все ключи агента;
2. **файловый ключ** `key_path``identity_file``~/.ssh/id_rsa`
(ключи с passphrase пока не поддерживаются);
3. иначе — понятная ошибка.
Проверка host key — TOFU поверх вашего `~/.ssh/known_hosts`: неизвестный хост
доверяется и запоминается, смена ключа сервера — громкая ошибка (MITM-защита).
## Переменные окружения (.env)
Если рядом с workdir проекта есть `.env`, его переменные (KEY=VALUE, `#`
комментарии, кавычки, префикс `export`) доступны всем локальным командам.
`.env` не копируется на сервер, если не указан явно в `sync`.
Приоритет источников: `[env]` из deploy.toml → `.env` → окружение ОС.
```env
# .env
NODE_ENV=production
API_TOKEN="secret"
export DB_URL=postgres://localhost/app
```
## Разработка
```sh
just test # fmt + clippy -D warnings + cargo test
just run # деплой из test/deploy.toml (в git не входит)
```