docs: add readme, MIT license
This commit is contained in:
+12
-1
@@ -1,6 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "xboctploy"
|
name = "xboctploy"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
description = "Lightweight CLI to deploy hobby projects from a local PC to a VPS over SSH"
|
||||||
|
license = "MIT"
|
||||||
|
readme = "README.md"
|
||||||
|
repository = "https://xboct-git.duckdns.org/Ku6epXBOCTuK/xboctploy"
|
||||||
|
keywords = ["deploy", "ssh", "sftp", "vps", "cli"]
|
||||||
|
categories = ["command-line-utilities", "development-tools"]
|
||||||
|
rust-version = "1.88"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -8,7 +15,11 @@ anyhow = "1.0.104"
|
|||||||
clap = { version = "4.6.6", features = ["derive"] }
|
clap = { version = "4.6.6", features = ["derive"] }
|
||||||
colored = "3.1.1"
|
colored = "3.1.1"
|
||||||
home = "0.5.12"
|
home = "0.5.12"
|
||||||
russh = { version = "0.62.7", default-features = false, features = ["ring", "rsa", "flate2"] }
|
russh = { version = "0.62.7", default-features = false, features = [
|
||||||
|
"ring",
|
||||||
|
"rsa",
|
||||||
|
"flate2",
|
||||||
|
] }
|
||||||
russh-sftp = "2.4.0"
|
russh-sftp = "2.4.0"
|
||||||
serde = { version = "1.0.229", features = ["derive"] }
|
serde = { version = "1.0.229", features = ["derive"] }
|
||||||
ssh2-config = "0.7.2"
|
ssh2-config = "0.7.2"
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Ku6epXBOCTuK
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
# xboctploy
|
||||||
|
|
||||||
|
Легковесная 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.80+. Кроссплатформенно: Windows (MSVC), Linux, macOS.
|
||||||
|
|
||||||
|
## Быстрый старт
|
||||||
|
|
||||||
|
```sh
|
||||||
|
xboctploy --list # показать проекты из конфига
|
||||||
|
xboctploy --dry-run demo # напечатать план деплоя без выполнения
|
||||||
|
xboctploy demo # задеплоить проект demo
|
||||||
|
```
|
||||||
|
|
||||||
|
Вывод:
|
||||||
|
|
||||||
|
```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/xboctploy/deploy.toml` — запуск «из любой папки».
|
||||||
|
|
||||||
|
Схема:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[projects.my-node-app]
|
||||||
|
workdir = "~/code/my-node-app" # где выполнять локальные команды (~ разворачивается)
|
||||||
|
host = "my-vps" # алиас из ~/.ssh/config или IP
|
||||||
|
user = "deploy" # опционально; иначе из ~/.ssh/config или юзер ОС
|
||||||
|
port = 2222 # опционально; иначе из ~/.ssh/config, иначе 22
|
||||||
|
key_path = "~/.ssh/id_ed25519" # опционально; иначе identity_file из ssh-config,
|
||||||
|
# иначе ~/.ssh/id_rsa
|
||||||
|
|
||||||
|
[projects.my-node-app.local] # шаги сборки на вашей машине
|
||||||
|
commands = ["npm ci", "npm run build"]
|
||||||
|
|
||||||
|
[[projects.my-node-app.sync]] # что заливать на сервер
|
||||||
|
source = "dist" # файл или папка (относительно workdir)
|
||||||
|
target = "/var/www/pages"
|
||||||
|
|
||||||
|
[projects.my-node-app.remote] # команды управления на сервере
|
||||||
|
commands = ["pm2 restart pages"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Приоритет параметров SSH: явное значение из deploy.toml → `~/.ssh/config` → дефолт.
|
||||||
|
|
||||||
|
### 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`.
|
||||||
|
`.env` не копируется на сервер, если не указан явно в `sync`.
|
||||||
|
|
||||||
|
```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 не входит)
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user