chore: harden spacetime publish provisioning
Some checks failed
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-05-03 03:38:10 +08:00
parent 62afaf620a
commit cc38057c3c
3 changed files with 116 additions and 1 deletions

View File

@@ -284,6 +284,115 @@ pipeline {
exit 1
}
read_env_value() {
local file="$1"
local key="$2"
local line value
if [[ ! -f "${file}" ]]; then
return
fi
while IFS= read -r line || [[ -n "${line}" ]]; do
if [[ "${line}" == "${key}="* ]]; then
value="${line#*=}"
value="$(printf "%s" "${value}" | tr -d "\\r")"
if [[ "${value}" == \"* && "${value}" == *\" ]]; then
value="${value#\"}"
value="${value%\"}"
fi
printf "%s" "${value}"
return
fi
done <"${file}"
}
write_env_value() {
local file="$1"
local key="$2"
local value="$3"
local tmp updated line
tmp="$(mktemp)"
updated="false"
while IFS= read -r line || [[ -n "${line}" ]]; do
if [[ "${line}" == "${key}="* ]]; then
if [[ "${updated}" != "true" ]]; then
printf "%s=%s\\n" "${key}" "${value}" >>"${tmp}"
updated="true"
fi
else
printf "%s\\n" "${line}" >>"${tmp}"
fi
done <"${file}"
if [[ "${updated}" != "true" ]]; then
printf "%s=%s\\n" "${key}" "${value}" >>"${tmp}"
fi
cat "${tmp}" >"${file}"
rm -f "${tmp}"
chmod 0600 "${file}"
chown root:root "${file}"
}
parse_json_string_field() {
local json="$1"
local key="$2"
printf "%s" "${json}" | sed -n "s/.*\\\"${key}\\\"[[:space:]]*:[[:space:]]*\\\"\\([^\\\"]*\\)\\\".*/\\1/p" | head -n 1
}
ensure_spacetime_owner_client_token() {
local server_url="http://127.0.0.1:3101"
local cli_path="${SPACETIME_ROOT}/bin/current/spacetimedb-cli"
local token identity response login_output existing_token identity_preview
if [[ "${DRY_RUN}" == "true" ]]; then
echo "+ ensure GENARRATIVE_SPACETIME_TOKEN in ${API_ENV_FILE}"
echo "+ generate SpacetimeDB client identity when token is missing"
echo "+ runuser -u spacetimedb -- ${cli_path} --root-dir ${SPACETIME_ROOT} login --token [REDACTED]"
return
fi
if [[ ! -f "${API_ENV_FILE}" ]]; then
echo "[server-provision] 环境文件不存在,无法写入 GENARRATIVE_SPACETIME_TOKEN: ${API_ENV_FILE}" >&2
exit 1
fi
if [[ ! -x "${cli_path}" ]]; then
echo "[server-provision] SpacetimeDB CLI 不存在或不可执行: ${cli_path}" >&2
exit 1
fi
existing_token="$(read_env_value "${API_ENV_FILE}" "GENARRATIVE_SPACETIME_TOKEN")"
if [[ -n "${existing_token}" ]]; then
token="${existing_token}"
echo "[server-provision] GENARRATIVE_SPACETIME_TOKEN 已存在,保留并同步 SpacetimeDB CLI 登录态。"
else
response="$(curl -fsS -X POST "${server_url}/v1/identity")"
identity="$(parse_json_string_field "${response}" "identity")"
identity="${identity:-$(parse_json_string_field "${response}" "Identity")}"
identity="${identity:-$(parse_json_string_field "${response}" "identity_hex")}"
identity="${identity:-$(parse_json_string_field "${response}" "identityHex")}"
token="$(parse_json_string_field "${response}" "token")"
token="${token:-$(parse_json_string_field "${response}" "Token")}"
if [[ -z "${identity}" || -z "${token}" ]]; then
echo "[server-provision] 生成 SpacetimeDB client identity 失败,响应缺少 identity/token。" >&2
exit 1
fi
write_env_value "${API_ENV_FILE}" "GENARRATIVE_SPACETIME_TOKEN" "${token}"
identity_preview="${identity:0:12}"
echo "[server-provision] 已生成 SpacetimeDB client identity 并写入 GENARRATIVE_SPACETIME_TOKEN: ${identity_preview}..."
fi
if ! login_output="$(runuser -u spacetimedb -- "${cli_path}" --root-dir "${SPACETIME_ROOT}" login --token "${token}" 2>&1)"; then
echo "[server-provision] 使用 GENARRATIVE_SPACETIME_TOKEN 登录 SpacetimeDB CLI 失败。" >&2
printf "%s\\n" "${login_output}" | sed -E "s/[A-Za-z0-9_.=-]{24,}/[REDACTED]/g" >&2
exit 1
fi
echo "[server-provision] 已同步 SpacetimeDB CLI 登录态;后续首次 publish 将使用同一 client identity。"
}
render_nginx_https_config() {
sed "s/genarrative.example.com/${SERVER_NAME}/g" deploy/nginx/genarrative.conf
}
@@ -506,6 +615,7 @@ pipeline {
run_cmd systemctl enable spacetimedb.service genarrative-api.service
run_cmd systemctl restart spacetimedb.service
wait_for_spacetimedb_service
ensure_spacetime_owner_client_token
if [[ -x "${CURRENT_LINK}/api-server" ]]; then
run_cmd systemctl restart genarrative-api.service
else