- deploy.sh: 目录级原子切换(current.new/current.old)替代 rm -rf 空窗式替换; 健康检查改为轮询 /api/version HTTP 接口;失败自动回滚上一版本 - 新增 deploy-watch.sh: 服务器本地 systemd timer 轮询 /ci-artifacts 产物指纹, 发现新版本自动部署——CI 与 AI 不再需要 SSH 到服务器执行任何命令 - server-deploy.yml: 部署包补入 web/ 后台静态资源;移除永不生效的前端构建死代码; 通知文案如实改为'构建成功'(部署由服务器侧 watcher 完成) - miniapp-preview.yml: 移除无意义的 --runInBand 测试参数 - 新增 PULL_DEPLOY.md 一次性安装文档(管理员手工执行)
47 lines
1.4 KiB
Bash
47 lines
1.4 KiB
Bash
#!/bin/bash
|
||
# 拉取式部署 watcher - 监听 CI 产物目录,发现新版本自动部署
|
||
# 设计原则:
|
||
# - CI 只负责构建并把产物写入 /ci-artifacts(runner 与本机同宿主)
|
||
# - 部署动作只由服务器本地的本脚本触发,任何 AI/CI 均不通过 SSH 操作服务器
|
||
# 安装方式见 .gitea/docs/PULL_DEPLOY.md(由管理员在服务器上手工执行一次)
|
||
|
||
set -u
|
||
|
||
ARTIFACT="${ARTIFACT:-/ci-artifacts/server-deploy-latest.tar.gz}"
|
||
STATE_FILE="${STATE_FILE:-/opt/lunar/production/.last-deployed-sha256}"
|
||
DEPLOY_SCRIPT="${DEPLOY_SCRIPT:-/opt/lunar/scripts/deploy.sh}"
|
||
LOG_FILE="${LOG_FILE:-/opt/lunar/deploy-watch.log}"
|
||
|
||
log() {
|
||
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE"
|
||
}
|
||
|
||
# 产物不存在时静默等待
|
||
if [ ! -f "$ARTIFACT" ]; then
|
||
exit 0
|
||
fi
|
||
|
||
# 计算产物指纹
|
||
CURRENT_SHA="$(sha256sum "$ARTIFACT" | awk '{print $1}')"
|
||
LAST_SHA=""
|
||
if [ -f "$STATE_FILE" ]; then
|
||
LAST_SHA="$(cat "$STATE_FILE")"
|
||
fi
|
||
|
||
# 无变化则跳过
|
||
if [ "$CURRENT_SHA" = "$LAST_SHA" ]; then
|
||
exit 0
|
||
fi
|
||
|
||
log "发现新版本产物 sha256=${CURRENT_SHA:0:12},开始部署"
|
||
|
||
# 执行部署;成功后才记录指纹(失败时下次轮询会重试)
|
||
if bash "$DEPLOY_SCRIPT" "$ARTIFACT" >> "$LOG_FILE" 2>&1; then
|
||
mkdir -p "$(dirname "$STATE_FILE")"
|
||
printf '%s' "$CURRENT_SHA" > "$STATE_FILE"
|
||
log "部署成功"
|
||
else
|
||
log "部署失败,保留旧指纹,等待下次轮询重试或人工介入"
|
||
exit 1
|
||
fi
|