Files
Genarrative/scripts/deploy/production-stdb-publish.sh
kdletters cc38057c3c
Some checks failed
CI / verify (pull_request) Has been cancelled
chore: harden spacetime publish provisioning
2026-05-03 03:38:10 +08:00

196 lines
5.4 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
用法:
./scripts/deploy/production-stdb-publish.sh --source-dir build/<version> --database <database> [--server-url http://127.0.0.1:3101] [--server local] [--root-dir /stdb] [--run-as-user spacetimedb] [--clear-database]
说明:
进入维护模式,校验 spacetime_module.wasm.sha256并在生产实例本机执行 spacetime publish。
默认使用 http://127.0.0.1:3101避免与部署机本机 Git/Web 服务的 3000 端口冲突。
默认使用 /stdb 作为 spacetime CLI root-dir并以 spacetimedb 用户发布,避免 root CLI 身份污染自托管实例。
发布时固定追加 --no-config只使用显式参数避免工作区或用户目录里的 spacetime 配置干扰目标。
失败时保留维护模式。
EOF
}
require_argument() {
local value="$1"
local label="$2"
if [[ -z "${value}" ]]; then
echo "[production-stdb-publish] 缺少参数: ${label}" >&2
exit 1
fi
}
validate_spacetime_database_name() {
local database="$1"
if [[ ! "${database}" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
echo "[production-stdb-publish] --database 必须匹配 ^[a-z0-9]+(-[a-z0-9]+)*$: ${database}" >&2
exit 1
fi
}
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
SOURCE_DIR=""
DATABASE=""
SERVER_ALIAS="local"
SERVER_URL="http://127.0.0.1:3101"
SPACETIME_ROOT_DIR="/stdb"
RUN_AS_USER="spacetimedb"
CLEAR_DATABASE=0
DEPLOY_COMPLETED=0
PUBLISH_TMP_DIR=""
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
--source-dir)
SOURCE_DIR="${2:?缺少 --source-dir 的值}"
shift 2
;;
--database)
DATABASE="${2:?缺少 --database 的值}"
shift 2
;;
--server)
SERVER_ALIAS="${2:?缺少 --server 的值}"
SERVER_URL=""
shift 2
;;
--server-url)
SERVER_URL="${2:?缺少 --server-url 的值}"
shift 2
;;
--root-dir)
SPACETIME_ROOT_DIR="${2:?缺少 --root-dir 的值}"
shift 2
;;
--run-as-user)
RUN_AS_USER="${2:?缺少 --run-as-user 的值}"
shift 2
;;
--clear-database)
CLEAR_DATABASE=1
shift
;;
*)
echo "[production-stdb-publish] 未知参数: $1" >&2
usage >&2
exit 1
;;
esac
done
require_argument "${SOURCE_DIR}" "--source-dir"
require_argument "${DATABASE}" "--database"
validate_spacetime_database_name "${DATABASE}"
if [[ ! "${SPACETIME_ROOT_DIR}" == /* || "${SPACETIME_ROOT_DIR}" == *".."* ]]; then
echo "[production-stdb-publish] --root-dir 必须是 Linux 绝对路径且不能包含 ..: ${SPACETIME_ROOT_DIR}" >&2
exit 1
fi
if [[ -n "${RUN_AS_USER}" && ! "${RUN_AS_USER}" =~ ^[A-Za-z_][A-Za-z0-9_-]*$ ]]; then
echo "[production-stdb-publish] --run-as-user 只能是本机用户名: ${RUN_AS_USER}" >&2
exit 1
fi
if [[ ! -d "${SOURCE_DIR}" ]]; then
echo "[production-stdb-publish] 发布目录不存在: ${SOURCE_DIR}" >&2
exit 1
fi
SOURCE_DIR="$(cd "${SOURCE_DIR}" && pwd)"
if [[ ! -f "${SOURCE_DIR}/spacetime_module.wasm" || ! -f "${SOURCE_DIR}/spacetime_module.wasm.sha256" ]]; then
echo "[production-stdb-publish] 缺少 spacetime_module.wasm 或 spacetime_module.wasm.sha256: ${SOURCE_DIR}" >&2
exit 1
fi
on_exit() {
local exit_code=$?
if [[ -n "${PUBLISH_TMP_DIR}" && -d "${PUBLISH_TMP_DIR}" ]]; then
rm -rf "${PUBLISH_TMP_DIR}"
fi
if [[ "${exit_code}" -ne 0 && "${DEPLOY_COMPLETED}" -ne 1 ]]; then
echo "[production-stdb-publish] 发布失败,保持维护模式。" >&2
fi
exit "${exit_code}"
}
trap on_exit EXIT
"${SCRIPT_DIR}/maintenance-on.sh" "spacetime module publish ${DATABASE}"
echo "[production-stdb-publish] 校验 wasm"
(
cd "${SOURCE_DIR}"
sha256sum -c spacetime_module.wasm.sha256
)
PUBLISH_ARGS=(
--root-dir="${SPACETIME_ROOT_DIR}"
publish
"${DATABASE}"
--bin-path "${SOURCE_DIR}/spacetime_module.wasm"
--yes
--no-config
)
if [[ -n "${SERVER_URL}" ]]; then
PUBLISH_ARGS+=(--server "${SERVER_URL}")
else
PUBLISH_ARGS+=(--server "${SERVER_ALIAS}")
fi
if [[ "${CLEAR_DATABASE}" -eq 1 ]]; then
PUBLISH_ARGS+=(--clear-database)
fi
if [[ -n "${SERVER_URL}" ]]; then
echo "[production-stdb-publish] 发布 SpacetimeDB module: ${DATABASE} -> ${SERVER_URL}, root=${SPACETIME_ROOT_DIR}"
else
echo "[production-stdb-publish] 发布 SpacetimeDB module: ${DATABASE} -> ${SERVER_ALIAS}, root=${SPACETIME_ROOT_DIR}"
fi
if [[ -n "${RUN_AS_USER}" && "$(id -u)" -eq 0 ]]; then
if ! id "${RUN_AS_USER}" >/dev/null 2>&1; then
echo "[production-stdb-publish] 发布用户不存在: ${RUN_AS_USER}" >&2
exit 1
fi
PUBLISH_TMP_DIR="$(mktemp -d /tmp/genarrative-stdb-publish.XXXXXX)"
install -m 0644 "${SOURCE_DIR}/spacetime_module.wasm" "${PUBLISH_TMP_DIR}/spacetime_module.wasm"
chown -R "${RUN_AS_USER}:${RUN_AS_USER}" "${PUBLISH_TMP_DIR}"
PUBLISH_ARGS=(
--root-dir="${SPACETIME_ROOT_DIR}"
publish
"${DATABASE}"
--bin-path "${PUBLISH_TMP_DIR}/spacetime_module.wasm"
--yes
--no-config
)
if [[ -n "${SERVER_URL}" ]]; then
PUBLISH_ARGS+=(--server "${SERVER_URL}")
else
PUBLISH_ARGS+=(--server "${SERVER_ALIAS}")
fi
if [[ "${CLEAR_DATABASE}" -eq 1 ]]; then
PUBLISH_ARGS+=(--clear-database)
fi
runuser -u "${RUN_AS_USER}" -- spacetime "${PUBLISH_ARGS[@]}"
else
spacetime "${PUBLISH_ARGS[@]}"
fi
"${SCRIPT_DIR}/maintenance-off.sh"
DEPLOY_COMPLETED=1
echo "[production-stdb-publish] 完成"