chore(release): 明确生产发布授权并支持集群发布

将发布与上线授权边界调整为一次明确的生产发布指令可连续执行 publish 和 deploy,同时保留仅构建镜像时的停止边界。

为现有发布脚本增加 compose/kubernetes helper 选择和显式 SSH 私钥支持,保持完整 SHA、digest 与生产基线校验不变。

验证:bash -n、ShellCheck、manual-release-test。
This commit is contained in:
2026-07-28 04:36:53 +08:00
parent 31565af07a
commit 2c7f8c14eb
3 changed files with 51 additions and 17 deletions
+28 -9
View File
@@ -3,7 +3,14 @@ set -euo pipefail
root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
production_host=${AI_GATEWAY_PRODUCTION_HOST:-root@110.42.51.33}
remote_helper=${AI_GATEWAY_REMOTE_RELEASE_HELPER:-/usr/local/sbin/easyai-ai-gateway-release}
deploy_mode=${AI_GATEWAY_DEPLOY_MODE:-compose}
case $deploy_mode in
compose) default_remote_helper=/usr/local/sbin/easyai-ai-gateway-release ;;
kubernetes) default_remote_helper=/usr/local/sbin/easyai-ai-gateway-cluster-release ;;
*) echo 'AI_GATEWAY_DEPLOY_MODE must be compose or kubernetes' >&2; exit 1 ;;
esac
remote_helper=${AI_GATEWAY_REMOTE_RELEASE_HELPER:-$default_remote_helper}
production_ssh_key=${AI_GATEWAY_PRODUCTION_SSH_KEY:-}
action=deploy
value=
@@ -14,8 +21,8 @@ Usage:
scripts/deploy-production-release.sh --rollback <historical-git-sha>
scripts/deploy-production-release.sh --status
This command changes production. Run it only after a separate successful
publish command and explicit user confirmation.
This command changes production. Run it only after a successful publish
command and an explicit user request to release or deploy to production.
EOF
}
@@ -48,9 +55,19 @@ esac
echo 'AI_GATEWAY_REMOTE_RELEASE_HELPER must be an absolute safe path' >&2
exit 1
}
ssh_options=(-o BatchMode=yes)
scp_options=(-q -o BatchMode=yes)
if [[ -n $production_ssh_key ]]; then
[[ $production_ssh_key == /* && -f $production_ssh_key && ! -L $production_ssh_key ]] || {
echo 'AI_GATEWAY_PRODUCTION_SSH_KEY must be an absolute regular file' >&2
exit 1
}
ssh_options+=(-i "$production_ssh_key")
scp_options+=(-i "$production_ssh_key")
fi
if [[ $action == status ]]; then
exec ssh -o BatchMode=yes "$production_host" "$remote_helper status"
exec ssh "${ssh_options[@]}" "$production_host" "$remote_helper status"
fi
if [[ $action == rollback ]]; then
@@ -58,7 +75,8 @@ if [[ $action == rollback ]]; then
echo 'rollback release must be a full lowercase Git SHA' >&2
exit 1
}
ssh -o BatchMode=yes "$production_host" "$remote_helper rollback $value"
# shellcheck disable=SC2029 # Both arguments are validated safe tokens above.
ssh "${ssh_options[@]}" "$production_host" "$remote_helper" rollback "$value"
echo "production_rollback=PASS release=$value"
exit 0
fi
@@ -76,11 +94,11 @@ status_file=$(mktemp)
cleanup() {
rm -f "$status_file"
ssh -o BatchMode=yes "$production_host" "rm -f $remote_manifest" >/dev/null 2>&1 || true
ssh "${ssh_options[@]}" "$production_host" rm -f -- "$remote_manifest" >/dev/null 2>&1 || true
}
trap cleanup EXIT HUP INT TERM
if ssh -o BatchMode=yes "$production_host" "$remote_helper status" >"$status_file" 2>/dev/null; then
if ssh "${ssh_options[@]}" "$production_host" "$remote_helper" status >"$status_file" 2>/dev/null; then
node "$root/scripts/release-manifest.mjs" validate "$status_file" >/dev/null
current_sha=$(node "$root/scripts/release-manifest.mjs" get "$status_file" sourceSha)
[[ $current_sha == "$base_sha" ]] || {
@@ -95,6 +113,7 @@ else
}
fi
scp -q "$manifest" "$production_host:$remote_manifest"
ssh -o BatchMode=yes "$production_host" "$remote_helper deploy $remote_manifest"
scp "${scp_options[@]}" "$manifest" "$production_host:$remote_manifest"
# shellcheck disable=SC2029 # remote_manifest is derived from a validated full SHA.
ssh "${ssh_options[@]}" "$production_host" "$remote_helper" deploy "$remote_manifest"
echo "production_deploy=PASS release=$source_sha"