Merge branch 'codex/backend-rewrite-spacetimedb' of http://82.157.175.59:3000/GenarrativeAI/Genarrative into codex/backend-rewrite-spacetimedb
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
本方案为当前仓库补齐 3 条 Jenkins 流水线:
|
||||
|
||||
1. `构建`:只负责在仓库根目录执行 `npm run deploy:rust:remote -- --skip-upload`,生成发布包。
|
||||
2. `部署`:只负责把指定发布版本部署到 `/home/ubuntu/Genarrative-deploy/`,禁止人工直接点击执行。
|
||||
2. `部署`:只负责把指定发布版本部署到 `/var/lib/jenkins/deploy/Genarrative/`,禁止人工直接点击执行。
|
||||
3. `构建并部署`:先构建,再把构建出的版本号传给 `部署` 流水线并等待部署完成。
|
||||
|
||||
本次只补 Jenkins 编排与本地部署脚本,不改现有 Rust 发布包构建逻辑,不恢复旧 `server-node` 部署链。
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
1. 构建产物目录统一使用 `build/<版本号>/`。
|
||||
2. 默认使用 Jenkins `BUILD_NUMBER` 作为版本号,避免依赖时间戳;如有需要也允许显式传 `BUILD_VERSION`。
|
||||
3. `部署` 流水线必须校验当前构建原因包含 `UpstreamCause`,没有上游触发则直接失败。
|
||||
3. `部署` 流水线必须校验当前构建原因包含上游触发 cause,没有上游触发则直接失败。
|
||||
4. `部署` 流水线额外校验上游作业名与传入的 `EXPECTED_UPSTREAM_JOB` 一致;如配置了环境变量 `GENARRATIVE_ALLOWED_UPSTREAM_JOB`,还必须与该值一致。
|
||||
5. `构建并部署` 在触发 `部署` 前先释放自己的构建节点,避免单执行器节点出现死锁。
|
||||
6. `部署` 不重新构建,不重新上传,不从 Jenkins 插件仓库复制产物,直接使用上游构建节点的本地 `build/<版本号>/` 目录。
|
||||
7. `部署` 流水线读取触发原因时必须使用 `currentBuild.getBuildCauses('hudson.model.Cause$UpstreamCause')` 这类白名单方法,不能直接访问 `currentBuild.rawBuild`,否则会被 Jenkins Script Security 拦截。
|
||||
7. `部署` 流水线读取触发原因时必须使用 `currentBuild.getBuildCauses(...)` 这类白名单方法,不能直接访问 `currentBuild.rawBuild`,否则会被 Jenkins Script Security 拦截。
|
||||
8. 由于 Jenkins Pipeline 的 `build` 步骤触发下游时,原因类型通常是 `org.jenkinsci.plugins.workflow.support.steps.build.BuildUpstreamCause`,实现上需要同时兼容它和经典的 `hudson.model.Cause$UpstreamCause`,否则会把真实的上游触发误判成人工执行。
|
||||
9. 如果线上进程的启停必须经过 `sudo`,只允许 `start.sh` / `stop.sh` 这两个 hook 使用 `sudo -n` 执行,部署目录清空与文件覆盖仍保持普通权限。
|
||||
|
||||
## 3. 节点与工作区要求
|
||||
|
||||
@@ -73,24 +75,27 @@ jenkins/Jenkinsfile.deploy
|
||||
|
||||
核心流程:
|
||||
|
||||
1. 校验触发原因必须是上游流水线,而不是人工点击。
|
||||
1. 校验触发原因必须是上游流水线,而不是人工点击;实现上同时兼容 `BuildUpstreamCause` 与经典 `UpstreamCause`。
|
||||
2. 校验 `BUILD_VERSION`、`SOURCE_WORKSPACE_ROOT`、`DEPLOY_DIRECTORY` 非空。
|
||||
3. 执行:
|
||||
|
||||
```bash
|
||||
scripts/jenkins-deploy-release.sh \
|
||||
--source-dir <SOURCE_WORKSPACE_ROOT>/build/<BUILD_VERSION> \
|
||||
--deploy-dir /home/ubuntu/Genarrative-deploy
|
||||
--deploy-dir /var/lib/jenkins/deploy/Genarrative \
|
||||
--hook-with-sudo
|
||||
```
|
||||
|
||||
脚本语义:
|
||||
|
||||
1. 若部署目录已有旧版本且存在 `stop.sh`,先执行旧版本 `stop.sh`。
|
||||
2. 直接清空部署目录中的全部旧文件。
|
||||
3. 将指定版本目录中的内容移动到部署目录。
|
||||
2. 只删除发布产物白名单中的旧文件,例如 `web/`、`api-server`、`spacetime_module.wasm`、`.env*`、`start.sh`、`stop.sh`、`web-server.mjs`、`README.md`。
|
||||
3. 将指定版本目录中的同名发布产物移动到部署目录。
|
||||
4. 执行新版本 `start.sh`。
|
||||
|
||||
这样可以满足你要求的“直接覆盖部署目录中的所有文件”。同时这也意味着部署目录内原有的 `.env`、`.env.local`、日志和本地 SpacetimeDB 数据都会被清掉,最终以构建产物中的文件为准。
|
||||
如果 `RUN_DEPLOY_HOOKS_WITH_SUDO=true`,第 1 步和第 4 步会改为 `sudo -n` 调用;这要求 Jenkins 运行用户提前配置免密 sudo,否则部署会直接失败,不会进入交互式密码提示。
|
||||
|
||||
这样可以满足“发布文件直接覆盖”的要求,同时保留部署目录里像 `spacetimedb-data/`、`logs/`、`run/` 这类运行态目录,不会因为部署被整体删除。发布白名单内的 `.env`、`.env.local` 仍会以构建产物中的文件为准。
|
||||
|
||||
### 4.3 构建并部署
|
||||
|
||||
@@ -122,6 +127,7 @@ jenkins/Jenkinsfile.build-and-deploy
|
||||
4. `RUN_NPM_CI`:是否在构建前执行 `npm ci`。
|
||||
|
||||
如果当前 Jenkins 没有额外配置独立 Agent,而是直接在控制器自身执行任务,`AGENT_LABEL` 应填写 `built-in`。
|
||||
如果 Jenkins 进程以默认 `jenkins` 用户运行,部署目录建议直接放在 `/var/lib/jenkins/deploy/Genarrative` 这类 Jenkins 自有目录下,避免再依赖 `/home/ubuntu/*` 的额外写权限。
|
||||
如果目标 Ubuntu 的 Jenkins `sh` 默认实际落到 `/bin/sh -> dash`,而流水线脚本又使用了 `set -euo pipefail`,则必须显式通过 `bash -lc` 执行命令,不能直接依赖 Jenkins 默认 `sh` 解释器。
|
||||
|
||||
其中仅 `部署` 流水线还需要:
|
||||
@@ -129,11 +135,22 @@ jenkins/Jenkinsfile.build-and-deploy
|
||||
1. `SOURCE_WORKSPACE_ROOT`
|
||||
2. `SOURCE_NODE_NAME`
|
||||
3. `DEPLOY_DIRECTORY`
|
||||
4. `EXPECTED_UPSTREAM_JOB`
|
||||
4. `RUN_DEPLOY_HOOKS_WITH_SUDO`
|
||||
5. `EXPECTED_UPSTREAM_JOB`
|
||||
|
||||
其中仅 `构建并部署` 流水线还需要:
|
||||
|
||||
1. `DEPLOY_JOB_NAME`
|
||||
2. `RUN_DEPLOY_HOOKS_WITH_SUDO`
|
||||
|
||||
如果你选择启用 `RUN_DEPLOY_HOOKS_WITH_SUDO=true`,推荐提前在服务器上增加一份最小 sudoers 配置,例如:
|
||||
|
||||
```text
|
||||
jenkins ALL=(root) NOPASSWD: /var/lib/jenkins/deploy/Genarrative/start.sh
|
||||
jenkins ALL=(root) NOPASSWD: /var/lib/jenkins/deploy/Genarrative/stop.sh
|
||||
```
|
||||
|
||||
这样可以把提权范围收敛到固定部署目录下的启停脚本,而不是把整个部署流程都交给 `sudo`。
|
||||
|
||||
## 6. 推荐 Job 命名
|
||||
|
||||
|
||||
@@ -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`。
|
||||
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 控制码写入日志文件。
|
||||
9. 默认执行 `scp -r -i ~\.ssh\dsk.pem build/<timestamp> ubuntu@82.157.175.59:/home/ubuntu/genarrative/` 上传发布包。
|
||||
|
||||
发布包结构:
|
||||
@@ -140,10 +140,12 @@ cd build/<timestamp>
|
||||
./stop.sh
|
||||
```
|
||||
|
||||
如果后续通过 Jenkins 的部署脚本把发布包覆盖到固定部署目录,部署阶段默认只替换 `web/`、`api-server`、`spacetime_module.wasm`、`.env*`、`start.sh`、`stop.sh`、`web-server.mjs`、`README.md` 等发布产物,不会删除部署目录中的 `spacetimedb-data/`、`logs/`、`run/` 这类运行态目录。
|
||||
|
||||
安全边界:
|
||||
|
||||
1. 构建脚本会把仓库根目录已有的 `.env`、`.env.local` 一并复制进发布包,因此运行前必须确认这些文件内容适合被带入目标环境。
|
||||
2. 如果仓库根目录不存在 `.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。
|
||||
5. 当前脚本是单目录进程启动方案,不替代生产 systemd、Nginx、TLS、日志轮转与守护进程配置。
|
||||
|
||||
Reference in New Issue
Block a user