- 50 命令:patrol/health/board/recall/poke/who/inbox/mind/message/team 等 - 异步并行 SSH (asyncio subprocess) - 命令注册表 + @command decorator + 插件扩展架构 - 环境检测 (Mac/VM/agent 身份) - JSON 输出契约 (stdout=成功, stderr=错误 code) - 权限模型 (agent 身份检测 + 环境限制) - pytest 23/23 通过 - deploy-joy.sh 全集群 16 VM 部署脚本 (含 PEP 668 兼容) - 旧 bash 版归档到 archive/commands.bash/ Closes: joy CLI 2.0 迁移
79 lines
2.6 KiB
Bash
79 lines
2.6 KiB
Bash
#!/usr/bin/env bash
|
||
# deploy-joy.sh — 部署 Python 版 joy CLI 到所有 VM
|
||
# 用法: ./deploy-joy.sh [vm1 vm2 ...] # 默认全集群
|
||
set -euo pipefail
|
||
|
||
JOY_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||
LINUXJOY="${HOME}/Projects/linuxjoy"
|
||
INVENTORY="${LINUXJOY}/inventory.yml"
|
||
SSH_OPTS="-o ConnectTimeout=10 -o BatchMode=yes"
|
||
|
||
echo "[deploy-joy] 部署 joy CLI 2.0 (Python) 到 VM..."
|
||
|
||
# 从 inventory 获取 VM 列表
|
||
get_vms() {
|
||
python3 -c "
|
||
import yaml
|
||
with open('${INVENTORY}') as f:
|
||
data = yaml.safe_load(f)
|
||
vms = []
|
||
for name, vm in data.get('vms', {}).items():
|
||
if vm.get('suspend', '') not in ('retired',):
|
||
vms.append(vm.get('ssh_alias', name))
|
||
print(' '.join(vms))
|
||
"
|
||
}
|
||
|
||
VMS=("$@")
|
||
if [[ ${#VMS[@]} -eq 0 ]]; then
|
||
read -ra VMS <<< "$(get_vms)"
|
||
fi
|
||
|
||
echo "[deploy-joy] 目标: ${VMS[*]}"
|
||
|
||
for vm in "${VMS[@]}"; do
|
||
echo "━━━ ${vm} ━━━"
|
||
|
||
# 1. 建目录
|
||
ssh ${SSH_OPTS} "$vm" "mkdir -p ~/Projects/joy-cli ~/bin" 2>/dev/null || {
|
||
echo " [${vm}] SSH 不通,跳过"
|
||
continue
|
||
}
|
||
|
||
# 2. rsync 项目文件(排除 .git 和 __pycache__)
|
||
echo " rsync joy-cli → ${vm}..."
|
||
rsync -a --delete -e "ssh ${SSH_OPTS}" \
|
||
--exclude='.git' --exclude='__pycache__' --exclude='*.pyc' \
|
||
--exclude='node_modules' \
|
||
"${JOY_ROOT}/" "${vm}:~/Projects/joy-cli/" 2>/dev/null
|
||
|
||
# 3. pip install -e(带 PEP 668 兼容)
|
||
echo " pip install..."
|
||
if ssh ${SSH_OPTS} "$vm" "cd ~/Projects/joy-cli && pip3 install -e . --quiet 2>/dev/null" 2>/dev/null; then
|
||
echo " pip install 成功"
|
||
elif ssh ${SSH_OPTS} "$vm" "cd ~/Projects/joy-cli && pip3 install -e . --quiet --break-system-packages 2>/dev/null" 2>/dev/null; then
|
||
echo " pip install (--break-system-packages) 成功"
|
||
else
|
||
echo " pip install 失败 → 创建 wrapper fallback"
|
||
# 把 wrapper 先写入本地临时文件再 scp,避免多层转义问题
|
||
local_wrapper="/tmp/joy-wrapper-${vm}"
|
||
cat > "$local_wrapper" << 'WRAPPER'
|
||
#!/usr/bin/env bash
|
||
export PYTHONPATH="${HOME}/Projects/joy-cli/src${PYTHONPATH:+:$PYTHONPATH}"
|
||
exec python3 -m joy "$@"
|
||
WRAPPER
|
||
scp ${SSH_OPTS} "$local_wrapper" "${vm}:~/bin/joy" 2>/dev/null
|
||
rm -f "$local_wrapper"
|
||
ssh ${SSH_OPTS} "$vm" "chmod +x ~/bin/joy" 2>/dev/null
|
||
echo " → wrapper 已创建"
|
||
fi
|
||
|
||
# 4. 验证
|
||
if ssh ${SSH_OPTS} "$vm" "joy --help 2>/dev/null | head -1" 2>/dev/null; then
|
||
echo " ✅ ${vm}: joy CLI 2.0 ready"
|
||
else
|
||
echo " ⚠️ ${vm}: 验证失败,检查 ~/bin/joy"
|
||
fi
|
||
done
|
||
|
||
echo "[deploy-joy] 完成"
|