From 12f68ca614fede68aaaead87b26155432e97e29d Mon Sep 17 00:00:00 2001 From: kdletters Date: Thu, 30 Apr 2026 09:45:47 +0800 Subject: [PATCH] Log SpacetimeDB database names in Jenkins deploy --- ..._RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md | 8 +++++--- ...DATABASE_MIGRATION_PIPELINES_2026-04-29.md | 2 +- ...ND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md | 4 +++- ...PACETIMEDB_MAINCLOUD_PUBLISH_2026-04-24.md | 4 +++- jenkins/Jenkinsfile.build-and-deploy | 5 +++-- scripts/deploy-rust-remote.sh | 19 ++++++++++++++----- scripts/spacetime-migration-common.mjs | 10 ++++++++++ scripts/spacetime-publish-maincloud.sh | 14 ++++++++++++++ 8 files changed, 53 insertions(+), 13 deletions(-) diff --git a/docs/technical/JENKINS_RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md b/docs/technical/JENKINS_RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md index 6587e455..d97ac6a9 100644 --- a/docs/technical/JENKINS_RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md +++ b/docs/technical/JENKINS_RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md @@ -25,7 +25,8 @@ 9. 由于 Jenkins Pipeline 的 `build` 步骤触发下游时,原因类型通常是 `org.jenkinsci.plugins.workflow.support.steps.build.BuildUpstreamCause`,实现上需要同时兼容它和经典的 `hudson.model.Cause$UpstreamCause`,否则会把真实的上游触发误判成人工执行。 10. 如果线上进程的启停必须经过 `sudo`,只允许 `start.sh` / `stop.sh` 这两个 hook 使用 `sudo -n` 执行,部署目录清空与文件覆盖仍保持普通权限。 11. `WEB_PORT` 必须在 `构建并部署` 与 `部署` 两条流水线之间使用同名参数传递;部署脚本会把最终端口写入固定部署目录 `.env.local` 的 `GENARRATIVE_WEB_PORT`,避免 `sudo` 启动 hook 时环境变量被清理导致端口回退。 -12. `DATABASE` 必须使用 SpacetimeDB CLI 可接受的名称字符:数字、字母、点和短横线;不要使用下划线,否则 `spacetime publish` 会报 `invalid characters in database name`。 +12. `DATABASE` 必须匹配 SpacetimeDB CLI 数据库名规则 `^[a-z0-9]+(-[a-z0-9]+)*$`:只能使用小写字母、数字,并用单个短横线分隔;大写字母、点号、下划线、首尾短横线和连续短横线都会被拒绝,否则 `spacetime publish` 会报 `invalid characters in database name`。 +13. Jenkins 日志必须能看到构建参数中的 SpacetimeDB 发布数据库,以及 `start.sh` 最终加载环境文件后的运行时数据库、server 和 root-dir,避免 `.env.local` 覆盖默认值后无法判断实际发布目标。 ## 3. 节点与工作区要求 @@ -123,7 +124,8 @@ jenkins/Jenkinsfile.build-and-deploy 3. 归档 `build//**`。 4. 记录当前 `NODE_NAME`、源码根目录、版本号。 5. 构建时额外透传 `--web-port `,默认生成监听 `25001` 的发布包。 -6. 触发 `部署` 流水线,并传递: +6. 构建日志会输出 `SpacetimeDB 发布数据库: `,发布包启动日志会输出最终 `database/server/root-dir`。 +7. 触发 `部署` 流水线,并传递: - `BUILD_VERSION` - `SOURCE_WORKSPACE_ROOT` - `SOURCE_NODE_NAME` @@ -171,7 +173,7 @@ jenkins/Jenkinsfile.build-and-deploy 4. `CLEAR_DATABASE` 5. `MIGRATE_ON_CONFLICT` 6. `MIGRATION_DIRECTORY` -7. `DATABASE`:发布包默认数据库名,默认 `genarrative-pipeline-local-test`,只能包含数字、字母、点和短横线。 +7. `DATABASE`:发布包默认数据库名,默认 `genarrative-pipeline-local-test`,必须匹配 `^[a-z0-9]+(-[a-z0-9]+)*$`。 如果你选择启用 `RUN_DEPLOY_HOOKS_WITH_SUDO=true`,推荐提前在服务器上增加一份最小 sudoers 配置,例如: diff --git a/docs/technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md b/docs/technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md index dbeaf674..b40f30b6 100644 --- a/docs/technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md +++ b/docs/technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md @@ -90,7 +90,7 @@ Genarrative-Database-Import `Genarrative-Build-And-Deploy` 增加以下本地发布包参数,便于在 Jenkins 中测试本地 SpacetimeDB,不依赖 Maincloud: -1. `DATABASE`:发布包默认数据库名,默认 `genarrative-pipeline-local-test`。SpacetimeDB CLI 当前只接受数字、字母、点和短横线,不要使用下划线。 +1. `DATABASE`:发布包默认数据库名,默认 `genarrative-pipeline-local-test`。SpacetimeDB CLI 当前要求数据库名匹配 `^[a-z0-9]+(-[a-z0-9]+)*$`,只能使用小写字母、数字,并用单个短横线分隔;不要使用大写字母、点号、下划线、首尾短横线或连续短横线。 2. `API_PORT`:发布包内 api-server 端口,默认 `8082`。 3. `WEB_PORT`:发布包内静态网站端口,默认 `25001`。 4. `SPACETIME_PORT`:发布包内本地 SpacetimeDB 端口,默认 `3101`。 diff --git a/docs/technical/RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md b/docs/technical/RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md index 7b633288..488b26e1 100644 --- a/docs/technical/RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md +++ b/docs/technical/RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md @@ -145,7 +145,9 @@ npm run deploy:rust:remote 8. 在目标目录写入 `start.sh` 与 `stop.sh`;`start.sh` 会先按 `KEY=value` 子集加载发布目录根部的 `.env`、`.env.local`,兼容 UTF-8 BOM 与 CRLF,再回退到构建时通过 `--database`、`--api-port`、`--web-port`、`--spacetime-host`、`--spacetime-port` 写入的默认值,并默认导出 `NO_COLOR=1` 与 `CARGO_TERM_COLOR=never`,避免 ANSI 控制码写入日志文件;同时按 Ubuntu 发布环境使用发布目录内 `.spacetimedb/` 作为 root-dir,不再额外设置 `--data-dir`,启动前先执行 `sync_ubuntu_spacetime_install`,优先从 `/usr/.local/share/spacetime/bin//spacetimedb-cli` 或 `$HOME/.local/share/spacetime/bin//spacetimedb-cli` 同步到 `.spacetimedb/bin/current/spacetimedb-cli`,当前线上 `spacetime` 入口为 `/usr/local/bin/spacetime`;启动参数为 `spacetime --root-dir ./.spacetimedb start --edition standalone --listen-addr :`,探活必须确认 `server ping` 输出包含 `Server is online:`;普通启动先无清库发布,若 publish 输出可判定为 schema 冲突,则自动导出旧库、清库发布新 wasm、导入回灌;如果以 `--clear-database` 启动,则内部 `spacetime publish` 会追加 `-c=on-conflict`,代表人工确认清库,不触发自动回灌。 9. 默认执行 `scp -r -i ~\.ssh\dsk.pem build/ ubuntu@82.157.175.59:/home/ubuntu/genarrative/` 上传发布包。 -SpacetimeDB database 名称只能包含数字、字母、点和短横线;不要使用下划线,否则 `spacetime publish` 会报 `invalid characters in database name`。发布包构建脚本和 `start.sh` 都会提前拦截这类非法名称。 +SpacetimeDB database 名称必须匹配 `^[a-z0-9]+(-[a-z0-9]+)*$`:只能使用小写字母、数字,并用单个短横线分隔;大写字母、点号、下划线、首尾短横线和连续短横线都会触发 `spacetime publish` 的 `invalid characters in database name`。发布包构建脚本和 `start.sh` 都会提前拦截这类非法名称。 + +发布包构建日志会输出 `SpacetimeDB 发布数据库: `;目标服务器执行 `start.sh` 时会在发布前输出最终加载后的 `database/server/root-dir`,用于确认 `.env.local` 或 Jenkins 参数覆盖后的实际发布目标。 发布包结构: diff --git a/docs/technical/SPACETIMEDB_MAINCLOUD_PUBLISH_2026-04-24.md b/docs/technical/SPACETIMEDB_MAINCLOUD_PUBLISH_2026-04-24.md index 59f5fcb1..3948086d 100644 --- a/docs/technical/SPACETIMEDB_MAINCLOUD_PUBLISH_2026-04-24.md +++ b/docs/technical/SPACETIMEDB_MAINCLOUD_PUBLISH_2026-04-24.md @@ -32,7 +32,8 @@ npm run spacetime:publish:maincloud 1. 使用 `cargo build -p spacetime-module --target wasm32-unknown-unknown --release` 构建 wasm。 2. 使用 `spacetime publish --server maincloud --bin-path --yes` 发布到 Maincloud。 -3. 输出 `api-server` 需要的 Maincloud 环境变量,便于部署进程复用。 +3. 发布前输出目标数据库名和 server,便于在 Jenkins 或手工日志中确认实际发布目标。 +4. 输出 `api-server` 需要的 Maincloud 环境变量,便于部署进程复用。 如需 schema 冲突时清库发布: @@ -56,6 +57,7 @@ npm run api-server:maincloud ## 设计约束 - Maincloud 数据库名必须显式配置,不能默认读取本地 `spacetime.local.json`。 +- Maincloud 数据库名必须匹配 `^[a-z0-9]+(-[a-z0-9]+)*$`,只能使用小写字母、数字,并用单个短横线分隔;否则 `spacetime publish` 会报 `invalid characters in database name`。 - 发布脚本只处理 SpacetimeDB 模块发布,不启动本地 SpacetimeDB。 - `api-server` 继续通过 `SpacetimeClientConfig` 的 `server_url / database / token` 连接数据库,不在前端增加逻辑。 - Windows 进程清理只能匹配本仓库 `server-rs/target/debug/api-server.exe` 的完整路径,不能按进程名泛化清理,避免影响其他 Rust 服务。 diff --git a/jenkins/Jenkinsfile.build-and-deploy b/jenkins/Jenkinsfile.build-and-deploy index 302630c8..6a420ff2 100644 --- a/jenkins/Jenkinsfile.build-and-deploy +++ b/jenkins/Jenkinsfile.build-and-deploy @@ -39,10 +39,11 @@ pipeline { if (!database) { error('DATABASE 不能为空。') } - if (!(database ==~ /^[0-9A-Za-z.-]+$/)) { - error("DATABASE 只能包含数字、字母、点和短横线,不能包含下划线,当前值: ${database}") + if (!(database ==~ /^[a-z0-9]+(-[a-z0-9]+)*$/)) { + error("DATABASE 必须匹配 SpacetimeDB 数据库名规则 ^[a-z0-9]+(-[a-z0-9]+)*$,只能使用小写字母、数字,并用单个短横线分隔,当前值: ${database}") } env.EFFECTIVE_DATABASE = database + echo "SpacetimeDB 发布数据库: ${env.EFFECTIVE_DATABASE}" def apiPort = params.API_PORT?.trim() if (!apiPort) { error('API_PORT 不能为空。') diff --git a/scripts/deploy-rust-remote.sh b/scripts/deploy-rust-remote.sh index 4d624910..25bfb61c 100644 --- a/scripts/deploy-rust-remote.sh +++ b/scripts/deploy-rust-remote.sh @@ -270,11 +270,13 @@ if [[ ! "${BUILD_NAME}" =~ ^[0-9A-Za-z._-]+$ ]]; then exit 1 fi -if [[ ! "${DATABASE}" =~ ^[0-9A-Za-z.-]+$ ]]; then - echo "[deploy:rust] --database 只能包含数字、字母、点和短横线,不能包含下划线: ${DATABASE}" >&2 +if [[ ! "${DATABASE}" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then + echo "[deploy:rust] --database 必须匹配 SpacetimeDB 数据库名规则 ^[a-z0-9]+(-[a-z0-9]+)*$,只能使用小写字母、数字,并用单个短横线分隔: ${DATABASE}" >&2 exit 1 fi +echo "[deploy:rust] SpacetimeDB 发布数据库: ${DATABASE}" + if [[ "${SKIP_SPACETIME_BUILD}" -eq 1 && "${MIGRATION_BOOTSTRAP_SECRET_MODE}" != "disabled" ]]; then echo "[deploy:rust] --skip-spacetime-build 无法把迁移引导密钥注入 wasm。" >&2 echo "[deploy:rust] 请移除 --skip-spacetime-build,或同时传 --no-migration-bootstrap-secret。" >&2 @@ -662,8 +664,8 @@ sanitize_path_segment() { validate_spacetime_database_name() { local database="$1" - if [[ ! "${database}" =~ ^[0-9A-Za-z.-]+$ ]]; then - echo "[start] GENARRATIVE_SPACETIME_DATABASE 只能包含数字、字母、点和短横线,不能包含下划线: ${database}" >&2 + if [[ ! "${database}" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then + echo "[start] GENARRATIVE_SPACETIME_DATABASE 必须匹配 SpacetimeDB 数据库名规则 ^[a-z0-9]+(-[a-z0-9]+)*$,只能使用小写字母、数字,并用单个短横线分隔: ${database}" >&2 exit 1 fi } @@ -985,9 +987,15 @@ start_process() { echo "$!" >"${pid_file}" } +validate_spacetime_database_name "${SPACETIME_DATABASE}" + +echo "[start] SpacetimeDB 发布配置:" +echo "[start] - database: ${SPACETIME_DATABASE}" +echo "[start] - server: ${SPACETIME_SERVER_URL}" +echo "[start] - root-dir: ${SPACETIME_ROOT_DIR}" + require_command node require_command spacetime -validate_spacetime_database_name "${SPACETIME_DATABASE}" mkdir -p "${PID_DIR}" "${LOG_DIR}" "${SPACETIME_ROOT_DIR}" sync_ubuntu_spacetime_install "${SPACETIME_ROOT_DIR}" @@ -1075,6 +1083,7 @@ echo "[start] 完成" echo "[start] Web: http://${WEB_HOST}:${WEB_PORT}" echo "[start] API: http://${API_HOST}:${API_PORT}" echo "[start] SpacetimeDB: ${SPACETIME_SERVER_URL}" +echo "[start] SpacetimeDB database: ${SPACETIME_DATABASE}" START_SCRIPT replace_placeholder_in_file "${TARGET_DIR}/start.sh" "__GENARRATIVE_DEFAULT_SPACETIME_HOST__" "${SPACETIME_HOST}" diff --git a/scripts/spacetime-migration-common.mjs b/scripts/spacetime-migration-common.mjs index 1f8abf29..99e93882 100644 --- a/scripts/spacetime-migration-common.mjs +++ b/scripts/spacetime-migration-common.mjs @@ -85,6 +85,7 @@ export function buildSpacetimeCallArgs(options, procedureName, input) { if (!options.database) { throw new Error('必须传入 --database。'); } + validateSpacetimeDatabaseName(options.database); const args = []; if (options.rootDir) { @@ -108,6 +109,7 @@ export async function callSpacetimeProcedure(options, procedureName, input) { if (!options.database) { throw new Error('必须传入 --database,或设置 GENARRATIVE_SPACETIME_DATABASE。'); } + validateSpacetimeDatabaseName(options.database); const serverUrl = resolveServerUrl(options).replace(/\/+$/u, ''); const url = `${serverUrl}/v1/database/${encodeURIComponent(options.database)}/call/${encodeURIComponent(procedureName)}`; @@ -195,6 +197,14 @@ export async function callSpacetimeProcedureViaCli(options, procedureName, input return parseProcedureResult(output); } +export function validateSpacetimeDatabaseName(database) { + if (!/^[a-z0-9]+(-[a-z0-9]+)*$/u.test(database)) { + throw new Error( + `SpacetimeDB 数据库名必须匹配 ^[a-z0-9]+(-[a-z0-9]+)*$,只能使用小写字母、数字,并用单个短横线分隔: ${database}`, + ); + } +} + export function parseProcedureResult(output) { const candidates = []; const trimmed = output.trim(); diff --git a/scripts/spacetime-publish-maincloud.sh b/scripts/spacetime-publish-maincloud.sh index 93acf35d..99a299f4 100644 --- a/scripts/spacetime-publish-maincloud.sh +++ b/scripts/spacetime-publish-maincloud.sh @@ -88,6 +88,15 @@ timestamp_slug() { node -e 'process.stdout.write(new Date().toISOString().replace(/[:.]/g, "-"));' } +validate_spacetime_database_name() { + local database="$1" + + if [[ ! "${database}" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then + echo "[spacetime:maincloud] --database 必须匹配 SpacetimeDB 数据库名规则 ^[a-z0-9]+(-[a-z0-9]+)*$,只能使用小写字母、数字,并用单个短横线分隔: ${database}" >&2 + exit 1 + fi +} + is_publish_conflict_output() { local output="$1" [[ "${output}" == *"conflict"* ]] \ @@ -209,6 +218,11 @@ if [[ -z "${SPACETIME_DATABASE}" ]]; then exit 1 fi +validate_spacetime_database_name "${SPACETIME_DATABASE}" + +echo "[spacetime:maincloud] SpacetimeDB 发布数据库: ${SPACETIME_DATABASE}" +echo "[spacetime:maincloud] SpacetimeDB server: ${SPACETIME_SERVER_ALIAS} (${SPACETIME_SERVER_URL})" + if ! command -v cargo >/dev/null 2>&1; then echo "[spacetime:maincloud] 缺少 cargo 命令。" >&2 exit 1