feat(ci): 迁移到 hk runner + Release 产物分发,解除对 doc79 runner 的依赖
- 两个工作流 runs-on 改为 hk(在线);Go/Node 工具链自包含下载+工作区缓存 - 后端产物改为发布 Gitea Release 附件(server-v<版本>),与 runner 位置解耦 - deploy-watch.sh 重写为从 Release 拉取:匿名/令牌 HTTPS 下载、包结构预检、 按 release id 幂等、失败下轮重试 - 移除对 /ci-artifacts 本机目录的依赖(原设计要求 runner 与生产同机) - PULL_DEPLOY.md 架构图同步更新
This commit is contained in:
@@ -1,47 +1,98 @@
|
||||
#!/bin/bash
|
||||
# 拉取式部署 watcher - 监听 CI 产物目录,发现新版本自动部署
|
||||
# 拉取式部署 watcher - 从 Gitea Release 拉取最新部署包并自动部署
|
||||
# 设计原则:
|
||||
# - CI 只负责构建并把产物写入 /ci-artifacts(runner 与本机同宿主)
|
||||
# - 部署动作只由服务器本地触发(1Panel 计划任务每分钟调用本脚本),
|
||||
# - CI 在任意 runner(hk 等)构建,产物以 Release 附件发布到 Gitea
|
||||
# - 本脚本由服务器本地定时任务(1Panel 计划任务)每分钟调用,通过 HTTPS 拉取,
|
||||
# 任何 AI/CI 均不通过 SSH 操作服务器
|
||||
# 安装方式见 .gitea/docs/PULL_DEPLOY.md(1Panel 原生方式,一次性配置)
|
||||
#
|
||||
# 可选环境变量(建议写入 /opt/lunar/production/.env 并在计划任务里 source):
|
||||
# GITEA_DEPLOY_TOKEN 只读令牌(仓库公开时可省略,匿名即可下载)
|
||||
|
||||
set -u
|
||||
|
||||
ARTIFACT="${ARTIFACT:-/ci-artifacts/server-deploy-latest.tar.gz}"
|
||||
STATE_FILE="${STATE_FILE:-/opt/lunar/production/.last-deployed-sha256}"
|
||||
GITEA_URL="${GITEA_URL:-https://gitea.neatcn.com}"
|
||||
REPO="${REPO:-gouki/lunar-mini}"
|
||||
STATE_FILE="${STATE_FILE:-/opt/lunar/production/.last-deployed-release}"
|
||||
DEPLOY_SCRIPT="${DEPLOY_SCRIPT:-/opt/lunar/scripts/deploy.sh}"
|
||||
LOG_FILE="${LOG_FILE:-/opt/lunar/deploy-watch.log}"
|
||||
WORK_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
log() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
# 产物不存在时静默等待
|
||||
if [ ! -f "$ARTIFACT" ]; then
|
||||
AUTH_ARGS=()
|
||||
if [ -n "${GITEA_DEPLOY_TOKEN:-}" ]; then
|
||||
AUTH_ARGS=(-H "Authorization: token ${GITEA_DEPLOY_TOKEN}")
|
||||
fi
|
||||
|
||||
# 查询最新 20 个 release,取 tag 前缀为 server-v 且带 deploy.tar.gz 附件的最新一个
|
||||
RELEASE_JSON=$(curl -fsS --connect-timeout 10 --max-time 30 \
|
||||
"${AUTH_ARGS[@]}" \
|
||||
"$GITEA_URL/api/v1/repos/$REPO/releases?limit=20" \
|
||||
-o "$WORK_DIR/releases.json" && cat "$WORK_DIR/releases.json") || {
|
||||
log "查询 release 列表失败,等待下次轮询"
|
||||
exit 1
|
||||
}
|
||||
|
||||
PARSED=$(python3 - "$WORK_DIR/releases.json" <<'PY'
|
||||
import json, sys
|
||||
releases = json.load(open(sys.argv[1]))
|
||||
for r in releases:
|
||||
if not r.get("tag_name", "").startswith("server-v"):
|
||||
continue
|
||||
if r.get("draft") or r.get("prerelease"):
|
||||
continue
|
||||
for a in r.get("assets", []):
|
||||
if a.get("name") == "deploy.tar.gz":
|
||||
print(r["id"])
|
||||
print(r["tag_name"])
|
||||
print(a["id"])
|
||||
print(a["browser_download_url"])
|
||||
sys.exit(0)
|
||||
PY
|
||||
) || true
|
||||
|
||||
if [ -z "$PARSED" ]; then
|
||||
# 尚无可部署的发布版本,静默等待
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 计算产物指纹
|
||||
CURRENT_SHA="$(sha256sum "$ARTIFACT" | awk '{print $1}')"
|
||||
LAST_SHA=""
|
||||
if [ -f "$STATE_FILE" ]; then
|
||||
LAST_SHA="$(cat "$STATE_FILE")"
|
||||
fi
|
||||
RELEASE_ID=$(echo "$PARSED" | sed -n 1p)
|
||||
TAG=$(echo "$PARSED" | sed -n 2p)
|
||||
ASSET_ID=$(echo "$PARSED" | sed -n 3p)
|
||||
DOWNLOAD_URL=$(echo "$PARSED" | sed -n 4p)
|
||||
|
||||
# 无变化则跳过
|
||||
if [ "$CURRENT_SHA" = "$LAST_SHA" ]; then
|
||||
# 幂等:已部署过该 release 则跳过
|
||||
LAST="$(cat "$STATE_FILE" 2>/dev/null || true)"
|
||||
if [ "$LAST" = "$RELEASE_ID" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "发现新版本产物 sha256=${CURRENT_SHA:0:12},开始部署"
|
||||
log "发现新版本 $TAG (release #$RELEASE_ID),开始拉取部署"
|
||||
|
||||
# 执行部署;成功后才记录指纹(失败时下次轮询会重试)
|
||||
if bash "$DEPLOY_SCRIPT" "$ARTIFACT" >> "$LOG_FILE" 2>&1; then
|
||||
# 下载部署包(公开仓库可匿名;-L 跟随重定向)
|
||||
if ! curl -fsSL --connect-timeout 10 --max-time 300 \
|
||||
"${AUTH_ARGS[@]}" \
|
||||
"$DOWNLOAD_URL" -o "$WORK_DIR/deploy.tar.gz"; then
|
||||
log "下载部署包失败,等待下次轮询重试"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 包结构预检(deploy.sh 内部还会再校验)
|
||||
if ! tar -tzf "$WORK_DIR/deploy.tar.gz" | grep -q "^deploy/bin/server$"; then
|
||||
log "部署包结构异常(缺少 deploy/bin/server),中止"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 执行部署;成功后才记录 release id(失败时下次轮询会重试)
|
||||
if bash "$DEPLOY_SCRIPT" "$WORK_DIR/deploy.tar.gz" >> "$LOG_FILE" 2>&1; then
|
||||
mkdir -p "$(dirname "$STATE_FILE")"
|
||||
printf '%s' "$CURRENT_SHA" > "$STATE_FILE"
|
||||
log "部署成功"
|
||||
printf '%s' "$RELEASE_ID" > "$STATE_FILE"
|
||||
log "部署成功: $TAG"
|
||||
else
|
||||
log "部署失败,保留旧指纹,等待下次轮询重试或人工介入"
|
||||
log "部署失败($TAG),保留旧版本,等待下次轮询重试或人工介入"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user