feat(deploy): 零SSH自动化部署——update.sh自动同步systemd单元/更新timer缩至1分钟/新增deploy.sh一键部署验证脚本

This commit is contained in:
gouki
2026-08-09 20:27:02 +00:00
parent dc2134cf5a
commit e4a8cc68b4
3 changed files with 106 additions and 3 deletions
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# vps-manager 本地一键部署(零 SSH
#
# 流程:
# 1. 检查工作区干净 → git push 到 Gitea
# 2. 轮询 cc1 的 /health(含 commit 字段)直到线上版本追平本地 HEAD
# cc1 上 vps-manager-update.timer 每 1 分钟自动拉取并重启)
# 3. 验证核心 API 全部 200
#
# 可配置项(环境变量):
# DEPLOY_HEALTH_URL 健康检查地址(默认 Tailscale HTTPS 域名)
# DEPLOY_TIMEOUT 等待超时秒数(默认 720;首次使用含旧 5 分钟 timer 周期余量)
# GIT_BRANCH 推送分支(默认 main)
#
# 用法:./deploy/deploy.sh
set -euo pipefail
HEALTH_URL="${DEPLOY_HEALTH_URL:-https://dify.taile5765c.ts.net/health}"
TIMEOUT="${DEPLOY_TIMEOUT:-720}"
BRANCH="${GIT_BRANCH:-main}"
POLL_INTERVAL=15
cd "$(dirname "$0")/.."
echo "==> [1/3] 推送代码"
if [ -n "$(git status --porcelain)" ]; then
echo "⚠️ 存在未提交变更,请先 commit:"
git status --short
exit 1
fi
git push origin "$BRANCH"
LOCAL=$(git rev-parse HEAD)
echo " 本地版本 ${LOCAL:0:8} 已推送,等待 cc1 自动更新…"
echo "==> [2/3] 等待 cc1 更新(轮询 $HEALTH_URL"
fetch_remote_commit() {
curl -s --max-time 10 "$HEALTH_URL" \
| python3 -c "import json,sys; print(json.load(sys.stdin).get('commit',''))" 2>/dev/null || echo ""
}
deadline=$(( $(date +%s) + TIMEOUT ))
REMOTE=""
while [ "$(date +%s)" -lt "$deadline" ]; do
REMOTE=$(fetch_remote_commit)
if [ "$REMOTE" = "$LOCAL" ]; then
echo " ✅ cc1 已更新至 ${LOCAL:0:8}"
break
fi
echo " 线上 ${REMOTE:0:8} | 目标 ${LOCAL:0:8}${POLL_INTERVAL}s 后重试…"
sleep "$POLL_INTERVAL"
done
if [ "$REMOTE" != "$LOCAL" ]; then
echo "❌ 部署超时(${TIMEOUT}s 内 cc1 未更新至 ${LOCAL:0:8},当前线上 ${REMOTE:0:8}"
echo " 排查:ssh cc1 'journalctl -u vps-manager-update.service -n 30'"
exit 1
fi
echo "==> [3/3] 验证核心 API"
BASE="${HEALTH_URL%/health}"
FAILED=0
for path in /api/assets /api/accounts /api/providers /api/stats/overview; do
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$BASE$path" || echo "000")
if [ "$code" = "200" ]; then
echo "$path -> $code"
else
echo "$path -> $code"
FAILED=1
fi
done
if [ "$FAILED" -ne 0 ]; then
echo "❌ 部署后验证失败,请检查 cc1 服务日志"
exit 1
fi
echo "🎉 部署完成:${LOCAL:0:8} 已在 cc1 生效并通过验证"
+27 -1
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# vps-manager 自动更新脚本(由 systemd timer 定时触发) # vps-manager 自动更新脚本(由 systemd timer 定时触发)
# 从 Gitea 拉取最新代码,如有更新则重启服务 # 1. 自动同步 deploy/ 下的 systemd 单元文件(有变更才拷贝 + daemon-reload
# 2. 从 Gitea 拉取最新代码,如有更新则装依赖并重启服务
# #
# 可配置项(环境变量): # 可配置项(环境变量):
# VPS_MANAGER_DIR 项目根目录(默认 /opt/vps-manager # VPS_MANAGER_DIR 项目根目录(默认 /opt/vps-manager
@@ -28,6 +29,31 @@ print_version() {
echo "[$(date '+%F %T')] 当前版本: v${semver} (${commit})" echo "[$(date '+%F %T')] 当前版本: v${semver} (${commit})"
} }
# 同步 systemd 单元文件:deploy/ 下的 .service/.timer 与 /etc/systemd/system
# 不一致时拷贝并 reloadtimer 变更额外 restart 使新调度周期立即生效。
# 每次都执行(而非仅版本更新时),保证单元变更不依赖代码变更触发。
sync_units() {
local changed=0 f base
for f in "$APP_DIR"/deploy/*.service "$APP_DIR"/deploy/*.timer; do
[ -f "$f" ] || continue
base=$(basename "$f")
if ! cmp -s "$f" "/etc/systemd/system/$base"; then
cp "$f" "/etc/systemd/system/$base"
echo "[$(date '+%F %T')] 单元已更新: $base"
changed=1
case "$base" in
*.timer) systemctl restart "$base" 2>/dev/null || true ;;
esac
fi
done
if [ "$changed" -eq 1 ]; then
systemctl daemon-reload
echo "[$(date '+%F %T')] systemd 单元同步完成"
fi
}
sync_units
git fetch -q origin "$BRANCH" git fetch -q origin "$BRANCH"
LOCAL=$(git rev-parse HEAD) LOCAL=$(git rev-parse HEAD)
+2 -2
View File
@@ -1,4 +1,4 @@
# vps-manager 自动更新定时器(每 5 分钟检查一次) # vps-manager 自动更新定时器(每 1 分钟检查一次,配合 deploy.sh 实现准实时自动部署
# 部署位置:/etc/systemd/system/vps-manager-update.timer # 部署位置:/etc/systemd/system/vps-manager-update.timer
[Unit] [Unit]
@@ -6,7 +6,7 @@ Description=Periodic update check for vps-manager
[Timer] [Timer]
OnBootSec=2min OnBootSec=2min
OnUnitActiveSec=5min OnUnitActiveSec=1min
Unit=vps-manager-update.service Unit=vps-manager-update.service
[Install] [Install]