chore: update spacetime deploy pipeline controls
This commit is contained in:
@@ -7,8 +7,8 @@
|
||||
本方案为当前仓库补齐 3 条 Jenkins 流水线:
|
||||
|
||||
1. `构建`:只负责在仓库根目录执行 `npm run deploy:rust:remote -- --skip-upload`,生成发布包。
|
||||
2. `部署`:只负责把指定发布版本部署到 `/var/lib/jenkins/deploy/Genarrative/`,禁止人工直接点击执行。
|
||||
3. `构建并部署`:先构建,再把构建出的版本号传给 `部署` 流水线并等待部署完成。
|
||||
2. `部署`:只负责把指定发布版本部署到 `/var/lib/jenkins/deploy/Genarrative/`,禁止人工直接点击执行,并支持按参数决定是否清空 SpacetimeDB 数据。
|
||||
3. `构建并部署`:先构建,再把构建出的版本号传给 `部署` 流水线并等待部署完成;同时暴露 `WEB_PORT` 参数,默认把发布包 Web 端口写成 `80`,并透传是否清库。
|
||||
|
||||
本次只补 Jenkins 编排与本地部署脚本,不改现有 Rust 发布包构建逻辑,不恢复旧 `server-node` 部署链。
|
||||
|
||||
@@ -83,6 +83,7 @@ jenkins/Jenkinsfile.deploy
|
||||
scripts/jenkins-deploy-release.sh \
|
||||
--source-dir <SOURCE_WORKSPACE_ROOT>/build/<BUILD_VERSION> \
|
||||
--deploy-dir /var/lib/jenkins/deploy/Genarrative \
|
||||
[--clear-database] \
|
||||
--hook-with-sudo
|
||||
```
|
||||
|
||||
@@ -91,7 +92,8 @@ scripts/jenkins-deploy-release.sh \
|
||||
1. 若部署目录已有旧版本且存在 `stop.sh`,先执行旧版本 `stop.sh`。
|
||||
2. 只删除发布产物白名单中的旧文件,例如 `web/`、`api-server`、`spacetime_module.wasm`、`.env*`、`start.sh`、`stop.sh`、`web-server.mjs`、`README.md`。
|
||||
3. 将指定版本目录中的同名发布产物移动到部署目录。
|
||||
4. 执行新版本 `start.sh`。
|
||||
4. 如果 `CLEAR_DATABASE=true`,部署脚本会以 `./start.sh --clear-database` 启动新版本;这样发布阶段的 `spacetime publish` 会追加 `-c always`。
|
||||
5. 执行新版本 `start.sh`。
|
||||
|
||||
如果 `RUN_DEPLOY_HOOKS_WITH_SUDO=true`,第 1 步和第 4 步会改为 `sudo -n` 调用;这要求 Jenkins 运行用户提前配置免密 sudo,否则部署会直接失败,不会进入交互式密码提示。
|
||||
|
||||
@@ -110,11 +112,13 @@ jenkins/Jenkinsfile.build-and-deploy
|
||||
1. 复用与 `构建` 相同的构建命令生成 `build/<BUILD_VERSION>/`。
|
||||
2. 归档 `build/<BUILD_VERSION>/**`。
|
||||
3. 记录当前 `NODE_NAME`、源码根目录、版本号。
|
||||
4. 触发 `部署` 流水线,并传递:
|
||||
4. 构建时额外透传 `--web-port <WEB_PORT>`,默认生成监听 `80` 的发布包。
|
||||
5. 触发 `部署` 流水线,并传递:
|
||||
- `BUILD_VERSION`
|
||||
- `SOURCE_WORKSPACE_ROOT`
|
||||
- `SOURCE_NODE_NAME`
|
||||
- `DEPLOY_DIRECTORY`
|
||||
- `CLEAR_DATABASE`
|
||||
- `EXPECTED_UPSTREAM_JOB`
|
||||
|
||||
## 5. Jenkins 参数建议
|
||||
@@ -125,6 +129,8 @@ jenkins/Jenkinsfile.build-and-deploy
|
||||
2. `GENARRATIVE_WORKSPACE_ROOT`:源码根目录;为空时回退到 Jenkins 当前工作区。
|
||||
3. `BUILD_VERSION`:发布版本号;为空时回退到 `BUILD_NUMBER`。
|
||||
4. `RUN_NPM_CI`:是否在构建前执行 `npm ci`。
|
||||
5. `WEB_PORT`:发布包内静态网站监听端口;`构建并部署` 默认值为 `80`。
|
||||
6. `CLEAR_DATABASE`:部署阶段是否清空 SpacetimeDB 数据后再发布 wasm;默认 `false`。
|
||||
|
||||
如果当前 Jenkins 没有额外配置独立 Agent,而是直接在控制器自身执行任务,`AGENT_LABEL` 应填写 `built-in`。
|
||||
如果 Jenkins 进程以默认 `jenkins` 用户运行,部署目录建议直接放在 `/var/lib/jenkins/deploy/Genarrative` 这类 Jenkins 自有目录下,避免再依赖 `/home/ubuntu/*` 的额外写权限。
|
||||
@@ -135,13 +141,16 @@ jenkins/Jenkinsfile.build-and-deploy
|
||||
1. `SOURCE_WORKSPACE_ROOT`
|
||||
2. `SOURCE_NODE_NAME`
|
||||
3. `DEPLOY_DIRECTORY`
|
||||
4. `RUN_DEPLOY_HOOKS_WITH_SUDO`
|
||||
5. `EXPECTED_UPSTREAM_JOB`
|
||||
4. `CLEAR_DATABASE`
|
||||
5. `RUN_DEPLOY_HOOKS_WITH_SUDO`
|
||||
6. `EXPECTED_UPSTREAM_JOB`
|
||||
|
||||
其中仅 `构建并部署` 流水线还需要:
|
||||
|
||||
1. `DEPLOY_JOB_NAME`
|
||||
2. `RUN_DEPLOY_HOOKS_WITH_SUDO`
|
||||
3. `WEB_PORT`
|
||||
4. `CLEAR_DATABASE`
|
||||
|
||||
如果你选择启用 `RUN_DEPLOY_HOOKS_WITH_SUDO=true`,推荐提前在服务器上增加一份最小 sudoers 配置,例如:
|
||||
|
||||
|
||||
@@ -104,7 +104,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. 把仓库根目录的 `.env` 与 `.env.local` 分别复制到目标目录根部和目标目录的 `web/` 下。
|
||||
7. 在目标目录写入 `web-server.mjs`,用于托管 `web/` 并把 `/api/*`、`/generated-*`、`/healthz` 反代到本包内的 `api-server`。
|
||||
8. 在目标目录写入 `start.sh` 与 `stop.sh`;`start.sh` 会先加载发布目录根部的 `.env`、`.env.local`,再回退到构建时通过 `--database`、`--api-port`、`--web-port`、`--spacetime-host`、`--spacetime-port` 写入的默认值,并默认导出 `NO_COLOR=1` 与 `CARGO_TERM_COLOR=never`,避免 ANSI 控制码写入日志文件。
|
||||
8. 在目标目录写入 `start.sh` 与 `stop.sh`;`start.sh` 会先加载发布目录根部的 `.env`、`.env.local`,再回退到构建时通过 `--database`、`--api-port`、`--web-port`、`--spacetime-host`、`--spacetime-port` 写入的默认值,并默认导出 `NO_COLOR=1` 与 `CARGO_TERM_COLOR=never`,避免 ANSI 控制码写入日志文件;如果以 `--clear-database` 启动,则内部 `spacetime publish` 会追加 `-c always`。
|
||||
9. 默认执行 `scp -r -i ~\.ssh\dsk.pem build/<timestamp> ubuntu@82.157.175.59:/home/ubuntu/genarrative/` 上传发布包。
|
||||
|
||||
发布包结构:
|
||||
@@ -147,7 +147,7 @@ cd build/<timestamp>
|
||||
1. 构建脚本会把仓库根目录已有的 `.env`、`.env.local` 一并复制进发布包,因此运行前必须确认这些文件内容适合被带入目标环境。
|
||||
2. 如果仓库根目录不存在 `.env` 或 `.env.local`,脚本会打印跳过日志,但不会因此失败;此时 `start.sh` 仅使用构建时写入的默认值与运行时显式传入的环境变量。
|
||||
3. `start.sh` 默认不清空 SpacetimeDB;只有显式执行 `./start.sh --clear-database` 才允许清库重发。
|
||||
4. `start.sh` 使用 `spacetime publish --bin-path spacetime_module.wasm --yes` 发布当前包内 wasm。
|
||||
4. `start.sh` 使用 `spacetime publish --bin-path spacetime_module.wasm --yes` 发布当前包内 wasm;清库模式下会追加 `-c always`。
|
||||
5. 当前脚本是单目录进程启动方案,不替代生产 systemd、Nginx、TLS、日志轮转与守护进程配置。
|
||||
6. 如只需要本地生成发布包,可传 `--skip-upload` 跳过默认 scp 上传。
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ spacetime generate --no-config --lang rust --out-dir D:\Genarrative\server-rs\cr
|
||||
1. bindings 生成失败时整个本地 dev 启动终止。
|
||||
2. 不手改 `server-rs/crates/spacetime-client/src/module_bindings` 生成物。
|
||||
3. Rust contract 变化后,以重新 generate 的 bindings 作为唯一真相。
|
||||
4. 不允许再对 `server-rs/crates/spacetime-client/src/module_bindings` 执行 `rustfmt`;`spacetime-client/src/lib.rs` 必须通过 `#[rustfmt::skip] pub mod module_bindings;` 阻止 workspace 级格式化递归改写生成物。
|
||||
|
||||
### 3.3 已知本地库迁移门禁
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ pipeline {
|
||||
string(name: 'AGENT_LABEL', defaultValue: 'built-in', description: '构建节点标签')
|
||||
string(name: 'GENARRATIVE_WORKSPACE_ROOT', defaultValue: '', description: '源码根目录,留空则使用当前 Jenkins 工作区')
|
||||
string(name: 'BUILD_VERSION', defaultValue: '', description: '发布版本号,留空则使用 Jenkins BUILD_NUMBER')
|
||||
string(name: 'WEB_PORT', defaultValue: '80', description: '发布包内静态网站端口,默认 80')
|
||||
booleanParam(name: 'CLEAR_DATABASE', defaultValue: false, description: '部署时是否清空 SpacetimeDB 数据后再发布 wasm')
|
||||
booleanParam(name: 'RUN_NPM_CI', defaultValue: false, description: '构建前是否执行 npm ci')
|
||||
string(name: 'DEPLOY_JOB_NAME', defaultValue: 'Genarrative-Deploy', description: '部署流水线作业名')
|
||||
string(name: 'DEPLOY_DIRECTORY', defaultValue: '/var/lib/jenkins/deploy/Genarrative', description: '固定部署目录')
|
||||
@@ -45,7 +47,8 @@ pipeline {
|
||||
sh """
|
||||
bash -lc '
|
||||
set -euo pipefail
|
||||
npm run deploy:rust:remote -- --skip-upload --name "${env.EFFECTIVE_BUILD_VERSION}"
|
||||
# 构建并部署流水线显式透传 Web 端口,确保部署包默认监听 80,同时允许 Jenkins 参数覆盖。
|
||||
npm run deploy:rust:remote -- --skip-upload --name "${env.EFFECTIVE_BUILD_VERSION}" --web-port "${params.WEB_PORT}"
|
||||
test -d "build/${env.EFFECTIVE_BUILD_VERSION}"
|
||||
'
|
||||
"""
|
||||
@@ -66,6 +69,7 @@ pipeline {
|
||||
string(name: 'SOURCE_WORKSPACE_ROOT', value: env.WORKSPACE_ROOT),
|
||||
string(name: 'BUILD_VERSION', value: env.EFFECTIVE_BUILD_VERSION),
|
||||
string(name: 'DEPLOY_DIRECTORY', value: params.DEPLOY_DIRECTORY),
|
||||
booleanParam(name: 'CLEAR_DATABASE', value: params.CLEAR_DATABASE),
|
||||
booleanParam(name: 'RUN_DEPLOY_HOOKS_WITH_SUDO', value: params.RUN_DEPLOY_HOOKS_WITH_SUDO),
|
||||
string(name: 'EXPECTED_UPSTREAM_JOB', value: env.JOB_NAME),
|
||||
]
|
||||
|
||||
@@ -11,6 +11,7 @@ pipeline {
|
||||
string(name: 'SOURCE_WORKSPACE_ROOT', defaultValue: '', description: '上游源码根目录')
|
||||
string(name: 'BUILD_VERSION', defaultValue: '', description: '待部署版本号')
|
||||
string(name: 'DEPLOY_DIRECTORY', defaultValue: '/var/lib/jenkins/deploy/Genarrative', description: '固定部署目录')
|
||||
booleanParam(name: 'CLEAR_DATABASE', defaultValue: false, description: '部署时是否清空 SpacetimeDB 数据后再发布 wasm')
|
||||
booleanParam(name: 'RUN_DEPLOY_HOOKS_WITH_SUDO', defaultValue: true, description: 'start.sh / stop.sh 是否通过 sudo -n 执行')
|
||||
string(name: 'EXPECTED_UPSTREAM_JOB', defaultValue: '', description: '允许触发本作业的上游作业名')
|
||||
}
|
||||
@@ -88,6 +89,9 @@ pipeline {
|
||||
--source-dir "build/${params.BUILD_VERSION}"
|
||||
--deploy-dir "${params.DEPLOY_DIRECTORY}"
|
||||
)
|
||||
if [[ "${params.CLEAR_DATABASE}" == "true" ]]; then
|
||||
deploy_args+=(--clear-database)
|
||||
fi
|
||||
if [[ "${params.RUN_DEPLOY_HOOKS_WITH_SUDO}" == "true" ]]; then
|
||||
deploy_args+=(--hook-with-sudo)
|
||||
fi
|
||||
|
||||
@@ -550,7 +550,8 @@ PUBLISH_ARGS=(
|
||||
)
|
||||
|
||||
if [[ "${CLEAR_DATABASE}" -eq 1 ]]; then
|
||||
PUBLISH_ARGS+=(--delete-data always)
|
||||
# 按当前 SpacetimeDB CLI 约定使用 -c=always,等价于 --delete-data always。
|
||||
PUBLISH_ARGS+=(-c always)
|
||||
fi
|
||||
|
||||
echo "[start] 发布 SpacetimeDB wasm: ${SPACETIME_DATABASE}"
|
||||
|
||||
@@ -5,17 +5,19 @@ set -euo pipefail
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
用法:
|
||||
./scripts/jenkins-deploy-release.sh --source-dir /path/to/build/123 --deploy-dir /var/lib/jenkins/deploy/Genarrative [--hook-with-sudo]
|
||||
./scripts/jenkins-deploy-release.sh --source-dir /path/to/build/123 --deploy-dir /var/lib/jenkins/deploy/Genarrative [--clear-database] [--hook-with-sudo]
|
||||
|
||||
说明:
|
||||
1. 如果部署目录已有旧版本且存在 stop.sh,则先执行旧版本 stop.sh。
|
||||
2. 仅删除并替换发布产物文件,保留部署目录中的运行数据目录。
|
||||
3. 把指定发布目录中的内容覆盖到部署目录。
|
||||
4. 最后执行新版本 start.sh。
|
||||
4. 如指定 --clear-database,则以清库模式执行新版本 start.sh。
|
||||
5. 最后执行新版本 start.sh。
|
||||
|
||||
参数:
|
||||
--source-dir <path> 必填,待部署的发布目录,例如 build/123
|
||||
--deploy-dir <path> 必填,固定部署目录,例如 /var/lib/jenkins/deploy/Genarrative
|
||||
--clear-database 可选,启动新版本时追加 --clear-database
|
||||
--hook-with-sudo 可选,仅对 start.sh/stop.sh 使用 sudo -n 执行
|
||||
EOF
|
||||
}
|
||||
@@ -32,6 +34,7 @@ require_argument() {
|
||||
|
||||
SOURCE_DIR=""
|
||||
DEPLOY_DIR=""
|
||||
CLEAR_DATABASE="0"
|
||||
HOOK_WITH_SUDO="0"
|
||||
DEPLOY_ITEMS=(
|
||||
".env"
|
||||
@@ -59,6 +62,10 @@ while [[ $# -gt 0 ]]; do
|
||||
DEPLOY_DIR="${2:?缺少 --deploy-dir 的值}"
|
||||
shift 2
|
||||
;;
|
||||
--clear-database)
|
||||
CLEAR_DATABASE="1"
|
||||
shift
|
||||
;;
|
||||
--hook-with-sudo)
|
||||
HOOK_WITH_SUDO="1"
|
||||
shift
|
||||
@@ -77,6 +84,7 @@ require_argument "${DEPLOY_DIR}" "--deploy-dir"
|
||||
run_hook() {
|
||||
local hook_dir="$1"
|
||||
local hook_name="$2"
|
||||
shift 2
|
||||
local hook_path="${hook_dir}/${hook_name}"
|
||||
|
||||
if [[ ! -x "${hook_path}" ]]; then
|
||||
@@ -89,7 +97,7 @@ run_hook() {
|
||||
echo "[jenkins-deploy] 使用 sudo 执行 ${hook_name}: ${hook_path}"
|
||||
(
|
||||
cd "${hook_dir}"
|
||||
sudo -n "${hook_path}"
|
||||
sudo -n "${hook_path}" "$@"
|
||||
) || {
|
||||
echo "[jenkins-deploy] sudo 执行 ${hook_name} 失败,请确认 jenkins 用户已配置免密 sudo 权限。" >&2
|
||||
exit 1
|
||||
@@ -99,7 +107,7 @@ run_hook() {
|
||||
|
||||
(
|
||||
cd "${hook_dir}"
|
||||
"./${hook_name}"
|
||||
"./${hook_name}" "$@"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -147,6 +155,11 @@ if [[ -f "${DEPLOY_DIR}/stop.sh" ]]; then
|
||||
fi
|
||||
|
||||
echo "[jenkins-deploy] 启动新版本: ${DEPLOY_DIR}"
|
||||
run_hook "${DEPLOY_DIR}" "start.sh"
|
||||
if [[ "${CLEAR_DATABASE}" == "1" ]]; then
|
||||
echo "[jenkins-deploy] 以清库模式启动新版本"
|
||||
run_hook "${DEPLOY_DIR}" "start.sh" --clear-database
|
||||
else
|
||||
run_hook "${DEPLOY_DIR}" "start.sh"
|
||||
fi
|
||||
|
||||
echo "[jenkins-deploy] 完成"
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
3. 设计身份透传与连接配置策略
|
||||
4. 设计 Axum / worker / 测试环境下的客户端复用方式
|
||||
|
||||
## 2.1 `module_bindings` 生成物约束
|
||||
|
||||
`src/module_bindings` 目录下的 Rust 文件统一视为 SpacetimeDB CLI 生成产物,后续维护必须遵守:
|
||||
|
||||
1. 只允许通过 `spacetime generate --lang rust` 刷新,不允许手工修改。
|
||||
2. 不允许对该目录执行 `rustfmt`,避免把 CLI 原始输出改写成额外格式化噪音。
|
||||
3. `src/lib.rs` 已通过 `#[rustfmt::skip] pub mod module_bindings;` 显式阻止 workspace 级 `cargo fmt` 继续递归格式化该目录。
|
||||
|
||||
## 3. 边界约束
|
||||
|
||||
1. `spacetime-client` 只承接 SpacetimeDB 客户端访问适配,不承接具体业务模块的规则实现。
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// `module_bindings` 是 SpacetimeDB CLI 生成产物,禁止再被 rustfmt 二次改写。
|
||||
#[rustfmt::skip]
|
||||
pub mod module_bindings;
|
||||
|
||||
use std::{
|
||||
|
||||
Reference in New Issue
Block a user