diff --git a/backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md b/backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md index 9832baaa..e6a7056b 100644 --- a/backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md +++ b/backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md @@ -22,7 +22,7 @@ - [x] 设计数据迁移脚本 - [x] 设计回滚策略 - [x] 准备本地 Rust 一键联调脚本(`npm run dev:rust` 同时启动前端、Rust `api-server` 与本地 SpacetimeDB) -- [x] 准备 Ubuntu 发布包构建脚本(`npm run build:rust:ubuntu` 生成 `build//`,包含 `web/`、`api-server`、`spacetime_module.wasm`、`start.sh`、`stop.sh`) +- [x] 准备 Ubuntu 发布包构建脚本(`npm run build:rust:ubuntu` 生成 `build//`,包含 `web/`、`api-server`、`spacetime_module.wasm`、`start.sh`、`stop.sh`,并默认 scp 上传到目标服务器) ## 3. 观测能力 diff --git a/docs/technical/README.md b/docs/technical/README.md index 070eb585..3c8d7daa 100644 --- a/docs/technical/README.md +++ b/docs/technical/README.md @@ -4,7 +4,7 @@ ## 文档列表 -- [RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md](./RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md):冻结 Rust 本地一键联调脚本与 Ubuntu 发布包构建脚本的执行口径,覆盖 `npm run dev:rust`、`npm run build:rust:ubuntu`、Vite release、Linux `api-server`、SpacetimeDB wasm、启动停止脚本和安全清库开关。 +- [RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md](./RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md):冻结 Rust 本地一键联调脚本与 Ubuntu 发布包构建脚本的执行口径,覆盖 `npm run dev:rust`、`npm run build:rust:ubuntu`、Vite release、Linux `api-server`、SpacetimeDB wasm、启动停止脚本、默认 scp 上传和安全清库开关。 - [RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md](./RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md):记录当前 Rust `api-server` 已挂载的 96 条 Axum 路由,按 auth、assets、runtime、custom world、story、generated path 等挂载面归类,用于对照 Node 能力基线与切流 smoke 清单。 - [BACKEND_REWRITE_CROSS_CUTTING_GOVERNANCE_2026-04-22.md](./BACKEND_REWRITE_CROSS_CUTTING_GOVERNANCE_2026-04-22.md):冻结后端重写收口阶段的横向治理规则,覆盖 TypeScript contract 到 Rust DTO 映射、SpacetimeDB schema 演进、大对象 / workflow cache 存储边界和文档维护门禁。 - [PLATFORM_LLM_TEXT_GATEWAY_DESIGN_2026-04-21.md](./PLATFORM_LLM_TEXT_GATEWAY_DESIGN_2026-04-21.md):`platform-llm` 文本模型网关首版设计,冻结 OpenAI 兼容 `/chat/completions`、SSE 增量解析、错误模型与重试边界。 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 c09b7507..a26a586f 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 @@ -7,7 +7,7 @@ 本方案补齐 `server-rs` 在 M7 切流前需要的两类工程脚本: 1. 本地一键联调脚本:同时启动本地 SpacetimeDB、Rust `api-server` 与 Web 前端,并通过现有 Vite 代理开关把运行时 API 指向 Rust。 -2. Ubuntu 发布包构建脚本:在仓库根目录生成 `build/<当前时间>/` 发布目录,内含前端 release、Linux `api-server`、SpacetimeDB wasm、启动脚本与停止脚本。 +2. Ubuntu 发布包构建脚本:在仓库根目录生成 `build/<当前时间>/` 发布目录,内含前端 release、Linux `api-server`、SpacetimeDB wasm、启动脚本与停止脚本,并默认通过 `scp` 上传到目标服务器。 脚本只做部署与联调编排,不改变 HTTP contract、SpacetimeDB schema 命名、对象存储键规划和前端默认 Node 开发入口。 @@ -96,6 +96,7 @@ npm run deploy:rust:remote 5. 执行 `cargo build -p spacetime-module --release --target wasm32-unknown-unknown --manifest-path server-rs/Cargo.toml`,并把 `spacetime_module.wasm` 复制到目标目录。 6. 在目标目录写入 `web-server.mjs`,用于托管 `web/` 并把 `/api/*`、`/generated-*`、`/healthz` 反代到本包内的 `api-server`。 7. 在目标目录写入 `start.sh` 与 `stop.sh`。 +8. 默认执行 `scp -r -i ~\.ssh\dsk.pem build/ ubuntu@82.157.175.59:/home/ubuntu/genarrative/` 上传发布包。 发布包结构: @@ -115,6 +116,7 @@ build// ```bash npm run build:rust:ubuntu -- --name 20260422-153000 npm run build:rust:ubuntu -- --database genarrative-dev --web-port 3000 --api-port 8082 --spacetime-port 3101 +npm run build:rust:ubuntu -- --skip-upload ``` 目标服务器启动: @@ -132,6 +134,7 @@ cd build/ 3. `start.sh` 默认不清空 SpacetimeDB;只有显式执行 `./start.sh --clear-database` 才允许清库重发。 4. `start.sh` 使用 `spacetime publish --bin-path spacetime_module.wasm --yes` 发布当前包内 wasm。 5. 当前脚本是单目录进程启动方案,不替代生产 systemd、Nginx、TLS、日志轮转与守护进程配置。 +6. 如只需要本地生成发布包,可传 `--skip-upload` 跳过默认 scp 上传。 目标服务器最小要求: diff --git a/scripts/deploy-rust-remote.sh b/scripts/deploy-rust-remote.sh index 881dfc37..07d4a9fb 100644 --- a/scripts/deploy-rust-remote.sh +++ b/scripts/deploy-rust-remote.sh @@ -21,6 +21,10 @@ usage() { --api-port api-server 端口,默认 8082 --web-port 静态网站端口,默认 3000 --spacetime-port SpacetimeDB 端口,默认 3101 + --ssh-key 上传使用的 SSH 私钥,默认 ~\.ssh\dsk.pem + --remote 上传目标 SSH 主机,默认 ubuntu@82.157.175.59 + --remote-dir 上传目标目录,默认 /home/ubuntu/genarrative + --skip-upload 只生成本地发布包,不上传服务器 --skip-web-build 跳过 Vite 构建,仅用于调试 --skip-api-build 跳过 api-server 构建,仅用于调试 --skip-spacetime-build 跳过 wasm 构建,仅用于调试 @@ -53,6 +57,34 @@ copy_required_file() { cp "${source_path}" "${target_path}" } +normalize_local_path_for_bash() { + local value="$1" + + if [[ "${value}" == "~"* ]]; then + local rest="${value:1}" + rest="${rest#\\}" + rest="${rest#/}" + rest="${rest//\\//}" + printf "%s/%s" "${HOME}" "${rest}" + return + fi + + if [[ "${value}" =~ ^([A-Za-z]):\\(.*)$ ]]; then + local drive + drive="$(printf "%s" "${BASH_REMATCH[1]}" | tr '[:upper:]' '[:lower:]')" + local rest="${BASH_REMATCH[2]//\\//}" + printf "/%s/%s" "${drive}" "${rest}" + return + fi + + printf "%s" "${value}" +} + +remote_shell_quote() { + local value="$1" + printf "'%s'" "$(printf "%s" "${value}" | sed "s/'/'\\\\''/g")" +} + SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" SERVER_RS_DIR="${REPO_ROOT}/server-rs" @@ -65,6 +97,10 @@ WEB_HOST="0.0.0.0" WEB_PORT="3000" SPACETIME_HOST="127.0.0.1" SPACETIME_PORT="3101" +SSH_KEY='~\.ssh\dsk.pem' +REMOTE_TARGET="ubuntu@82.157.175.59" +REMOTE_DIR="/home/ubuntu/genarrative" +UPLOAD_ENABLED=1 SKIP_WEB_BUILD=0 SKIP_API_BUILD=0 SKIP_SPACETIME_BUILD=0 @@ -108,6 +144,22 @@ while [[ $# -gt 0 ]]; do SPACETIME_PORT="${2:?缺少 --spacetime-port 的值}" shift 2 ;; + --ssh-key) + SSH_KEY="${2:?缺少 --ssh-key 的值}" + shift 2 + ;; + --remote) + REMOTE_TARGET="${2:?缺少 --remote 的值}" + shift 2 + ;; + --remote-dir) + REMOTE_DIR="${2:?缺少 --remote-dir 的值}" + shift 2 + ;; + --skip-upload) + UPLOAD_ENABLED=0 + shift + ;; --skip-web-build) SKIP_WEB_BUILD=1 shift @@ -159,6 +211,19 @@ if [[ "${SKIP_WEB_BUILD}" -ne 1 ]]; then require_command npm fi +NORMALIZED_SSH_KEY="$(normalize_local_path_for_bash "${SSH_KEY}")" + +if [[ "${UPLOAD_ENABLED}" -eq 1 ]]; then + require_command ssh + require_command scp + + if [[ ! -f "${NORMALIZED_SSH_KEY}" ]]; then + echo "[deploy:rust] SSH 私钥不存在: ${SSH_KEY}" >&2 + echo "[deploy:rust] Git Bash 解析路径: ${NORMALIZED_SSH_KEY}" >&2 + exit 1 + fi +fi + mkdir -p "${WEB_DIR}" echo "[deploy:rust] 发布包目录: ${TARGET_DIR}" @@ -535,4 +600,13 @@ cat >"${TARGET_DIR}/README.md" < ${REMOTE_TARGET}:${REMOTE_DIR}/" + scp -r -i "${NORMALIZED_SSH_KEY}" "${TARGET_DIR}" "${REMOTE_TARGET}:${REMOTE_DIR}/" +fi + echo "[deploy:rust] 完成: ${TARGET_DIR}"