chore: gate memind_adm gray release candidates

This commit is contained in:
john
2026-07-21 17:01:59 +08:00
parent e08eb50775
commit 7f20c4ce87
7 changed files with 273 additions and 21 deletions
+88 -17
View File
@@ -22,7 +22,10 @@ MANIFEST_PATH="${TMP_DIR}/memind-adm-${RELEASE_ID}.manifest.txt"
SHA_PATH="${TMP_DIR}/memind-adm-${RELEASE_ID}.sha256"
MEMIND_SRC="${TEST_MEMIND_ROOT:-${ROOT}/../Memind}"
MEMIND_LIB="${ROOT}/memind-lib"
DRY_RUN=0
MEMIND_BASE_REF="${MEMIND_BASE_REF:-origin/main}"
IMAGE_MAKE_RELEASE_ID="${IMAGE_MAKE_RELEASE_ID:-not-declared}"
PACKAGE_ONLY=0
OUTPUT_DIR=""
SKIP_BUILD=0
AUTO_YES=0
@@ -34,15 +37,19 @@ trap cleanup EXIT
usage() {
cat <<'EOF'
用法:
bash scripts/release-prod.sh [--dry-run] [--skip-build] [--yes]
bash scripts/release-prod.sh [--package-only|--dry-run] [--output-dir DIR] [--skip-build] [--yes]
说明:
1. 本地构建 dist 并打包运行产物(不含 src/ 等开发源码)
2. 上传到 103
3. 103 全量备份当前 memind_adm
4. 解包、安装依赖(不在 103 构建前端)
5. 原子切换 live 目录并重启验证
6. 旧 live 目录移入 archives,103 不再保留可编辑源码树
1. 校验 memind_adm 与 Memind 共享源码均来自干净、可追溯的 commit
2. 本地构建 dist 并打包运行产物(不含 src/ 等开发源码)
3. --package-only / --dry-run 只生成持久候选包,不连接或修改 103
4. 正式模式上传到 103,完成全量备份、原子切换、重启和健康检查
5. live 目录移入 archives,103 不再保留可编辑源码树
环境:
TEST_MEMIND_ROOT 干净的 Memind 共享源码目录,默认 ../Memind
MEMIND_BASE_REF Memind 共享源码必须精确匹配的 ref,默认 origin/main
IMAGE_MAKE_RELEASE_ID 写入 manifest 的 image_make 依赖版本
禁止:
- 直接 rsync 到 103
@@ -53,7 +60,12 @@ EOF
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run) DRY_RUN=1 ;;
--dry-run|--package-only) PACKAGE_ONLY=1 ;;
--output-dir)
shift
[[ $# -gt 0 ]] || { echo "--output-dir 缺少目录参数" >&2; exit 2; }
OUTPUT_DIR="$1"
;;
--skip-build) SKIP_BUILD=1 ;;
--yes|-y) AUTO_YES=1 ;;
-h|--help)
@@ -93,14 +105,52 @@ else
exit 1
fi
git -C "${MEMIND_SRC}" rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
echo "Memind 共享源码不是可追溯 Git 工作区: ${MEMIND_SRC}" >&2
exit 1
}
if [[ -n "$(git -C "${MEMIND_SRC}" status --porcelain=v1 --untracked-files=all)" ]]; then
echo "Memind 共享源码工作区不干净,禁止打包: ${MEMIND_SRC}" >&2
git -C "${MEMIND_SRC}" status --short --untracked-files=all >&2
exit 1
fi
git -C "${MEMIND_SRC}" rev-parse --verify --quiet "${MEMIND_BASE_REF}" >/dev/null || {
echo "Memind 共享源码缺少基线 ref: ${MEMIND_BASE_REF}" >&2
exit 1
}
MEMIND_GIT_HEAD="$(git -C "${MEMIND_SRC}" rev-parse HEAD)"
MEMIND_BASE_HEAD="$(git -C "${MEMIND_SRC}" rev-parse "${MEMIND_BASE_REF}")"
if [[ "${MEMIND_GIT_HEAD}" != "${MEMIND_BASE_HEAD}" ]]; then
echo "Memind 共享源码必须精确匹配 ${MEMIND_BASE_REF}" >&2
echo " HEAD=${MEMIND_GIT_HEAD}" >&2
echo " ${MEMIND_BASE_REF}=${MEMIND_BASE_HEAD}" >&2
exit 1
fi
for required_shared_file in \
user-auth.mjs \
asset-gateway.mjs \
image-make-admin-config.mjs \
image-make-client.mjs; do
[[ -f "${MEMIND_SRC}/${required_shared_file}" ]] || {
echo "Memind 共享源码缺少发布依赖: ${required_shared_file}" >&2
exit 1
}
done
[[ -f "${IGNORE_FILE}" ]] || {
echo "缺少忽略文件: ${IGNORE_FILE}" >&2
exit 1
}
say "本地预检查"
ssh -o BatchMode=yes -o ConnectTimeout=15 "${HOST}" "echo release-ssh-ok" >/dev/null
ssh -o BatchMode=yes "${HOST}" "test -d '${APP_DIR}' && test -f '${APP_DIR}/package.json'" >/dev/null
if [[ "${PACKAGE_ONLY}" -ne 1 ]]; then
say "103 正式发布预检查"
ssh -o BatchMode=yes -o ConnectTimeout=15 "${HOST}" "echo release-ssh-ok" >/dev/null
ssh -o BatchMode=yes "${HOST}" "test -d '${APP_DIR}' && test -f '${APP_DIR}/package.json'" >/dev/null
fi
if [[ "${SKIP_BUILD}" -ne 1 ]]; then
say "本地构建 dist103 不再执行前端构建)"
@@ -120,7 +170,6 @@ fi
exit 1
}
MEMIND_GIT_HEAD="$(git -C "${MEMIND_SRC}" rev-parse HEAD 2>/dev/null || echo unknown)"
MEMIND_GIT_BRANCH="$(git -C "${MEMIND_SRC}" branch --show-current 2>/dev/null || echo detached)"
say "打包 Memind 共享模块到 memind-lib"
@@ -150,6 +199,14 @@ fi
echo "memind-lib 缺少 user-auth.mjs" >&2
exit 1
}
[[ -f "${MEMIND_LIB}/image-make-admin-config.mjs" ]] || {
echo "memind-lib 缺少 image_make 管理配置模块" >&2
exit 1
}
[[ -f "${MEMIND_LIB}/image-make-client.mjs" ]] || {
echo "memind-lib 缺少 image_make 客户端模块" >&2
exit 1
}
[[ -f "${MEMIND_LIB}/skills/excel-analyst/SKILL.md" ]] || {
echo "memind-lib 缺少 Excel Analyst 技能" >&2
exit 1
@@ -163,7 +220,7 @@ grep -q 'tkmind-excel' "${MEMIND_LIB}/capabilities.mjs" || {
exit 1
}
if [[ "${AUTO_YES}" -ne 1 && "${DRY_RUN}" -ne 1 ]]; then
if [[ "${AUTO_YES}" -ne 1 && "${PACKAGE_ONLY}" -ne 1 ]]; then
say "发布确认"
echo "目标主机: ${HOST}"
echo "目标目录: ${APP_DIR}"
@@ -185,6 +242,10 @@ say "生成发布清单"
echo "git_branch=$(git -C "${ROOT}" branch --show-current 2>/dev/null || echo detached)"
echo "memind_git_head=${MEMIND_GIT_HEAD}"
echo "memind_git_branch=${MEMIND_GIT_BRANCH}"
echo "memind_base_ref=${MEMIND_BASE_REF}"
echo "memind_base_head=${MEMIND_BASE_HEAD}"
echo "memind_git_status=clean"
echo "image_make_release_id=${IMAGE_MAKE_RELEASE_ID}"
echo "git_status_begin"
git -C "${ROOT}" status --short --branch || true
echo "git_status_end"
@@ -199,9 +260,19 @@ tar \
checksum="$(shasum -a 256 "${BUNDLE_PATH}" | awk '{print $1}')"
printf '%s %s\n' "${checksum}" "$(basename "${BUNDLE_PATH}")" > "${SHA_PATH}"
if [[ "${DRY_RUN}" -eq 1 ]]; then
say "dry-run 完成"
ls -lh "${BUNDLE_PATH}" "${MANIFEST_PATH}" "${SHA_PATH}"
if [[ "${PACKAGE_ONLY}" -eq 1 ]]; then
if [[ -z "${OUTPUT_DIR}" ]]; then
OUTPUT_DIR="${ROOT}/release-candidates/${RELEASE_ID}"
elif [[ "${OUTPUT_DIR}" != /* ]]; then
OUTPUT_DIR="${ROOT}/${OUTPUT_DIR}"
fi
mkdir -p "${OUTPUT_DIR}"
cp "${BUNDLE_PATH}" "${MANIFEST_PATH}" "${SHA_PATH}" "${OUTPUT_DIR}/"
say "候选包生成完成;未连接或修改 103"
echo "candidate_dir=${OUTPUT_DIR}"
ls -lh "${OUTPUT_DIR}/$(basename "${BUNDLE_PATH}")" \
"${OUTPUT_DIR}/$(basename "${MANIFEST_PATH}")" \
"${OUTPUT_DIR}/$(basename "${SHA_PATH}")"
exit 0
fi