Files
Genarrative/docs/technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md

29 KiB
Raw Blame History

生产部署计划

更新时间2026-05-02

当前落地进度

已落地生产基础设施骨架与首批生产 Jenkinsfile

  • deploy/systemd/spacetimedb.service
  • deploy/systemd/genarrative-api.service
  • deploy/nginx/genarrative.conf
  • deploy/nginx/snippets/genarrative-maintenance.conf
  • deploy/env/api-server.env.example
  • scripts/deploy/maintenance-on.sh
  • scripts/deploy/maintenance-off.sh
  • scripts/deploy/maintenance-status.sh
  • scripts/build-production-release.sh
  • scripts/jenkins-checkout-source.sh
  • scripts/deploy/production-web-deploy.sh
  • scripts/deploy/production-api-deploy.sh
  • scripts/deploy/production-stdb-publish.sh
  • jenkins/Jenkinsfile.production-web-build
  • jenkins/Jenkinsfile.production-web-deploy
  • jenkins/Jenkinsfile.production-api-build
  • jenkins/Jenkinsfile.production-api-deploy
  • jenkins/Jenkinsfile.production-stdb-module-build
  • jenkins/Jenkinsfile.production-stdb-module-publish
  • jenkins/Jenkinsfile.production-full-build-and-deploy
  • jenkins/Jenkinsfile.production-server-provision
  • jenkins/Jenkinsfile.production-database-export
  • jenkins/Jenkinsfile.production-database-import
  • npm run build:production-release

旧 Jenkins 一体化发布链对应的 Jenkinsfile 已从仓库移除,生产构建和发布入口统一切到 jenkins/Jenkinsfile.production-*scripts/deploy-rust-remote.sh 等旧发布包脚本暂保留为历史迁移参考,不再作为生产 Jenkins Job 的入口。

目标

将当前部署方式调整为单机生产推荐方案:生产运行路径不使用 Docker不再使用旧的一体化启动脚本由 systemd 托管 SpacetimeDB 与 Rust api-server,由 Nginx 托管主站、后台前端与必要反向代理。

本计划用于重新创建 Jenkins 流水线、服务器环境配置、网站发布、api-server 发布、SpacetimeDB 模块发布,以及数据库人工导入导出流程。

生产架构

  • Nginx 作为唯一公网入口,负责 HTTPS、静态站点、后台静态页面、维护页与 /admin/api/ 反向代理。
  • SpacetimeDB 作为系统服务运行,监听 127.0.0.1:3000,数据根目录为 /stdb
  • Rust api-server 作为系统服务运行,监听 127.0.0.1:8082,只被 Nginx 的 /admin/api/ 访问。
  • 主站与后台前端构建为静态文件,发布到服务器固定目录,不放入 Jenkins 目录,也不跟随 Docker 镜像。
  • 除网站静态发布外,api-server 发布、SpacetimeDB 模块发布、数据库导入、服务器配置变更都必须先进入维护模式。

服务器目录

  • /opt/genarrative/releases/<version>/:每次发布的完整版本目录。
  • /opt/genarrative/current:指向当前生效版本的软链接。
  • /srv/genarrative/web:指向 /opt/genarrative/current/web,供 Nginx 托管静态站点。
  • /etc/genarrative/api-server.envapi-server 生产环境变量文件。
  • /var/lib/genarrative/maintenance/enabled:维护模式开关文件。
  • /stdbSpacetimeDB 程序、配置与数据根目录。

生产密钥

/etc/genarrative/api-server.env 中的生产密钥指所有只能存在于生产服务器、不能进入 Git、不能进入构建产物的敏感配置。典型内容包括

  • LLM 或第三方服务 API Key。
  • 短信服务 Access Key 与 Secret。
  • 后台登录、会话、签名、加密相关密钥。
  • 生产 SpacetimeDB 地址与数据库名。
  • 只允许生产使用的回调地址、白名单或内部令牌。

该文件由服务器配置流水线或人工初始化创建,权限建议为 root:genarrative0640。Jenkins 构建任务不能读取该文件;只有生产发布或服务启动需要读取。

systemd 服务

SpacetimeDB

  • 服务名:spacetimedb.service
  • 运行用户:spacetimedb
  • 工作目录:/stdb
  • 启动命令:/stdb/spacetime --root-dir=/stdb start --listen-addr=127.0.0.1:3000
  • 对外暴露:默认不直接暴露公网端口。

该方案与 SpacetimeDB 官方自托管文档一致:使用 Ubuntu、专用用户、/stdb 根目录、systemd 服务和 Nginx。

api-server

  • 服务名:genarrative-api.service
  • 运行用户:genarrative
  • 工作目录:/opt/genarrative/current
  • 可执行文件:/opt/genarrative/current/api-server
  • 环境文件:/etc/genarrative/api-server.env
  • 监听地址:127.0.0.1:8082

api-server 不放入 Docker也不直接暴露公网端口。发布时替换版本目录并重启 genarrative-api.service

Nginx 规则

只保留必要入口:

  • /:主站静态页面。
  • /admin/:后台前端静态页面,后台构建时使用 /admin/ 作为 base path。
  • /admin/api/:反向代理到 http://127.0.0.1:8082/admin/api/
  • HTTP 到 HTTPS只保留 301 重定向。
  • /maintenance.html:维护中页面。

移除这些公网反向代理:

  • /api/*
  • /generated-*
  • 公网 /healthz
  • 其他旧的一体化 web server 代理入口。

SpacetimeDB 公网路由默认保持收敛,只按实际前端 SDK 需要暴露最小集合。禁止开放可远程发布数据库或管理实例的通用入口。

维护模式

维护模式由 /var/lib/genarrative/maintenance/enabled 控制:

  • 文件存在:进入维护模式。
  • 文件不存在:退出维护模式。

行为:

  • 网站静态资源发布不进入维护模式。
  • api-server 发布、SpacetimeDB 模块发布、数据库导入、服务器配置变更必须进入维护模式。
  • 普通页面在维护模式下展示 /maintenance.html
  • /admin/api/* 在维护模式下返回 503。
  • 静态资源仍允许访问,避免维护页样式和资源加载失败。
  • 发布成功后自动解除维护模式。
  • 发布失败时保持维护模式,并通过邮件通知人工处理。

构建产物

生产发布包构建入口:

npm run build:production-release -- --name <version>

每次构建产物按版本号归档:

build/<version>/
├─ web/
│  ├─ index.html
│  ├─ assets/
│  ├─ maintenance.html
│  └─ admin/
├─ web.tar.gz
├─ web.tar.gz.sha256
├─ api-server
├─ api-server.sha256
├─ spacetime_module.wasm
├─ spacetime_module.wasm.sha256
├─ release-manifest.json
├─ scripts/
│  ├─ database-export.mjs
│  ├─ database-import.mjs
│  ├─ spacetime-migration-common.mjs
│  ├─ maintenance-on.sh
│  ├─ maintenance-off.sh
│  └─ maintenance-status.sh
├─ deploy/
│  ├─ systemd/
│  │  ├─ spacetimedb.service
│  │  └─ genarrative-api.service
│  ├─ nginx/
│  │  ├─ genarrative.conf
│  │  └─ snippets/genarrative-maintenance.conf
│  └─ env/api-server.env.example
└─ README.md

web/ 可以保留在构建目录中供本地 smoke test 与人工排查使用,但 Jenkins Web Build 归档和 Web Deploy 传输必须以 web.tar.gz 为主,避免把大量静态碎文件逐个传回 Jenkins controller。api-serverspacetime_module.wasm 是单文件产物,默认直接归档单文件与对应 .sha256,不强制压缩。

不再生成旧产物:

  • web-server.mjs
  • 旧的一体化 start.sh
  • 旧的一体化 stop.sh

Jenkins 节点

Jenkins 可运行在 Windows 或其他机器上,本机 Windows 只作为人工触发入口;构建与发布动作只允许由 Jenkins 调度到 Linux agent 执行。当前已接入的 Linux agent 是开发/构建机,同时也是 development 环境部署机。

开发/构建/开发部署实例

  • Jenkins Job 参数不暴露真实节点名、IP 或带 IP 的标签。
  • 构建 Job 固定使用 label expressionlinux && genarrative-build
  • 当前开发/构建/开发部署 agent 必须同时配置 linuxgenarrative-build 两个标签;非 Linux 节点不能承担构建或部署。
  • 用途:拉代码、安装依赖、构建主站、构建后台、构建 api-server、构建 SpacetimeDB wasm、归档产物并执行 DEPLOY_TARGET=development 的开发环境部署。

生产/发布实例

  • Jenkins Job 参数不暴露真实节点名、IP 或带 IP 的标签。
  • 生产机已作为独立 Linux Jenkins agent 接入,节点名使用脱敏名称 genarrative-release-deploy-01,调度标签只使用 linuxgenarrative-release-deploy
  • 生产机真实连接地址只允许保存在 Jenkins 节点 SSH launcher 的 host 字段中不能写入节点名、调度标签、Job 参数默认值或文档推荐命令。
  • 发布 Job 通过 DEPLOY_TARGET 选择逻辑部署目标,再在 Jenkinsfile 内部映射到 Linux-only 脱敏调度表达式:development -> linux && genarrative-buildrelease -> linux && genarrative-release-deploy
  • 用途:服务器配置、发布静态网站、发布 api-server、发布 SpacetimeDB 模块、数据库导入导出、维护模式切换。

Git 仓库访问

Jenkins controller 与 Linux agent 看到的 Git 服务地址不同,必须拆成两层配置:

  • Jenkins Job 的 Pipeline script from SCM 由 controller 执行SCM URL 使用 controller 可访问的公网地址:http://82.157.175.59:3000/GenarrativeAI/Genarrative.git
  • Jenkinsfile 内部的源码、脚本 checkout 在 Linux agent 上执行,GIT_REMOTE_URL 使用 agent 本机可访问地址:http://127.0.0.1:3000/GenarrativeAI/Genarrative.git

因此生产 Jenkinsfile 不使用 checkout scm 作为构建源码入口,而是显式 checkout([$class: 'GitSCM', userRemoteConfigs: [[url: "${GIT_REMOTE_URL}"]], ...])。后续 scripts/jenkins-checkout-source.sh 会继续把 origin 设置为 GIT_REMOTE_URL,并按 SOURCE_BRANCH / COMMIT_HASH 拉取和校验目标提交。

127.0.0.1 只代表当前执行该阶段的 Linux agent 自身;如果 release agent 与 Git 服务不在同一台机器,必须把对应 Jenkinsfile 的 GIT_REMOTE_URL 改成 release agent 可访问的内网地址,不能让 release 发布阶段回退到 controller 公网拉取。

SSH PEM 凭证

在 Jenkins 中使用 SSH Username with private key 类型添加 PEM 私钥:

  • genarrative-dev-ssh-key:开发/构建实例 SSH 凭证。
  • genarrative-prod-root-ssh:当前开发/构建实例已使用的 SSH 凭证;生产/发布实例复用同一个凭证。

推荐使用非 root 用户,例如 jenkins。该用户只通过 sudoers 获得必要命令权限,例如 systemctl restart genarrative-apinginx -t、维护脚本、发布目录切换等。

Jenkins 流水线

生产 Jenkins 目标流水线:

  1. Genarrative-Server-Provision
  2. Genarrative-Web-Build
  3. Genarrative-Web-Deploy
  4. Genarrative-Api-Build
  5. Genarrative-Api-Deploy
  6. Genarrative-Stdb-Module-Build
  7. Genarrative-Stdb-Module-Publish
  8. Genarrative-Database-Export
  9. Genarrative-Database-Import
  10. Genarrative-Full-Build-And-Deploy

已落地的生产流水线脚本文件:

  • jenkins/Jenkinsfile.production-web-build
  • jenkins/Jenkinsfile.production-web-deploy
  • jenkins/Jenkinsfile.production-api-build
  • jenkins/Jenkinsfile.production-api-deploy
  • jenkins/Jenkinsfile.production-stdb-module-build
  • jenkins/Jenkinsfile.production-stdb-module-publish
  • jenkins/Jenkinsfile.production-full-build-and-deploy
  • jenkins/Jenkinsfile.production-server-provision
  • jenkins/Jenkinsfile.production-database-export
  • jenkins/Jenkinsfile.production-database-import

Genarrative-Database-ExportGenarrative-Database-Import 的生产版 Jenkinsfile 已落地;旧的数据库导入导出 Jenkinsfile 已删除,避免继续沿用旧部署目录和旧一体化发布链假设。

构建流水线运行在当前 Linux agent 的脱敏 label expression linux && genarrative-build。发布、导入导出和服务器配置流水线通过 DEPLOY_TARGET 映射到 Linux-only 脱敏部署表达式;其中 development 映射到当前 Linux 开发/构建/开发部署 agent 的 linux && genarrative-buildrelease 映射到独立 Linux 生产部署 agent 的 linux && genarrative-release-deploy,不能复用当前开发/构建/开发部署 agent。真实机器名、IP 和带 IP 的 Jenkins label 只允许留在 Jenkins 节点连接配置中,不能暴露为 Job 参数默认值、调度标签或文档推荐值。

发布流水线通过 Jenkins copyArtifacts(...) 从对应构建 Job 获取归档产物,因此 Jenkins 需要安装并启用 Copy Artifact 插件。数据库导入流水线的手动上传模式使用 stashedFile 文件参数,因此 Jenkins 还需要安装并启用 File Parameter 插件。生产发布不能退回到读取构建 workspace 本地目录的旧模式。

所有发布流水线必须提供 DEPLOY_TARGET 参数,用于选择逻辑部署目标:

  • 默认值:development,用于当前 Linux 开发/构建/开发部署 agent 上的开发环境部署,对应脱敏调度表达式 linux && genarrative-build
  • 备选值:release,对应生产发布目标,由独立 Linux 生产部署 agent 执行。

发布流水线的 agent 必须使用 DEPLOY_TARGET 在 Jenkinsfile 内部映射到脱敏 label expression并且表达式必须包含 linux避免在参数页面暴露真实节点名、IP 或带 IP 的 Jenkins label也避免非 Linux 节点执行构建或部署。release 目标还必须要求 CONFIRM_RELEASE_DEPLOY_AGENT=trueGenarrative-Full-Build-And-Deploy 也必须透传同一个 DEPLOY_TARGET,确保 Stdb publish、API deploy、Web deploy 三个部署动作落到同一类目标部署环境。

Rust 构建缓存与磁盘控制

Jenkins 在 agent 上执行构建时会为不同 Job 或不同构建创建独立 workspaceRust 默认把编译产物写入仓库内 server-rs/target/,会导致每个 workspace 都保留一份完整 target 目录,占用大量磁盘。生产构建流水线必须把 Rust 缓存固定到 workspace 外的稳定目录。

如果构建 agent 使用 root 账户执行,缓存目录不应写死为 /var/lib/jenkins。推荐优先使用单独数据盘,例如 /data/jenkins-cache/genarrative/;如果没有数据盘,可使用 /var/cache/genarrative-build/

mkdir -p /var/cache/genarrative-build/{cargo-home,cargo-target,sccache}
chmod 700 /var/cache/genarrative-build

Rust 构建流水线建议统一设置:

environment {
  CARGO_HOME = '/var/cache/genarrative-build/cargo-home'
  CARGO_TARGET_DIR = '/var/cache/genarrative-build/cargo-target/prod-release'
  CARGO_INCREMENTAL = '0'

  RUSTC_WRAPPER = 'sccache'
  SCCACHE_DIR = '/var/cache/genarrative-build/sccache'
  SCCACHE_CACHE_SIZE = '30G'
}

如使用数据盘,则把上述路径替换为:

environment {
  CARGO_HOME = '/data/jenkins-cache/genarrative/cargo-home'
  CARGO_TARGET_DIR = '/data/jenkins-cache/genarrative/cargo-target/prod-release'
  CARGO_INCREMENTAL = '0'

  RUSTC_WRAPPER = 'sccache'
  SCCACHE_DIR = '/data/jenkins-cache/genarrative/sccache'
  SCCACHE_CACHE_SIZE = '30G'
}

scripts/build-production-release.sh 必须尊重 CARGO_TARGET_DIR,不能硬编码从 server-rs/target/ 拷贝 Rust 产物。脚本中的产物路径应按以下口径计算:

CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-${SERVER_RS_DIR}/target}"
API_BINARY_SOURCE="${CARGO_TARGET_DIR}/x86_64-unknown-linux-gnu/release/api-server"
WASM_SOURCE="${CARGO_TARGET_DIR}/wasm32-unknown-unknown/release/spacetime_module.wasm"

并发与清理规则:

  • Rust 构建 Job 建议使用 disableConcurrentBuilds(),或对共享 CARGO_TARGET_DIR 加 Jenkins lock,避免多个同包 release 构建同时写入同一最终产物路径。
  • 生产发布流水线只能消费 build/<version>/ 或 Jenkins 归档产物,不允许从共享 cargo-target 目录直接发布。
  • SCCACHE_CACHE_SIZE 必须设置上限,避免编译缓存无限增长。
  • /var/cache/genarrative-build/cargo-target 或数据盘对应目录配置定期清理,建议保留最近 14 到 30 天。
  • Jenkins Job 必须配置构建记录和归档产物保留策略,避免历史 release 包长期堆积。

统一源码版本参数

所有构建流水线、发布流水线和 Genarrative-Full-Build-And-Deploy 都必须支持以下参数:

  • SOURCE_BRANCH:源码分支,默认 master,代表 origin/master 最新提交。
  • COMMIT_HASH:可选 Git commit hash留空时使用 origin/<SOURCE_BRANCH> 最新 commit填写时必须是 7 到 40 位十六进制 hash并且该 commit 必须属于 origin/<SOURCE_BRANCH>
  • DEPLOY_TARGET:逻辑部署目标选择参数。发布流水线和 Genarrative-Full-Build-And-Deploy 必填;构建流水线仅在 PUBLISH_AFTER_BUILD=true 时用于触发下游发布。

执行规则:

  • 流水线先按 Jenkins SCM 配置 checkout 仓库,再执行 git fetch --tags --prune origin "+refs/heads/<SOURCE_BRANCH>:refs/remotes/origin/<SOURCE_BRANCH>"
  • 如果工作区是浅克隆,流水线必须尝试 git fetch --unshallow --tags,确保能验证目标 commit 与分支关系。
  • COMMIT_HASH 为空时detached checkout 到 refs/remotes/origin/<SOURCE_BRANCH> 当前最新 commit。
  • COMMIT_HASH 非空时,先解析到完整 commit再用 git merge-base --is-ancestor <commit> refs/remotes/origin/<SOURCE_BRANCH> 校验该提交属于指定分支,校验通过后 detached checkout。
  • 流水线日志必须输出最终 SOURCE_BRANCH 与实际 SOURCE_COMMIT
  • 构建产物必须写入 release-manifest.json,至少包含 versionsource_branchsource_commitbuilt_at 和组件类型,供发布、回滚和审计使用。

构建流水线使用上述参数决定实际构建源码。发布流水线也暴露同名参数,但只用于选择本次发布使用的部署脚本、配置模板和 smoke test 逻辑;被发布的应用文件仍必须来自 Jenkins 归档产物或指定 release 包,不允许在发布流水线中重新构建。

当构建流水线以 PUBLISH_AFTER_BUILD=true 触发下游发布流水线时,必须把 SOURCE_BRANCH 和实际解析出的 SOURCE_COMMIT 作为下游 COMMIT_HASH 传递,确保部署逻辑和刚生成的产物可追溯到同一源码版本。

构建流水线支持参数 PUBLISH_AFTER_BUILD

  • false:只构建并归档产物。
  • true:构建成功后触发对应发布流水线。

发布流水线必须从归档产物获取文件,不依赖构建 workspace 的本地状态。

流水线职责

Genarrative-Server-Provision

用于生产服务器一次性或低频配置:

  • 创建 spacetimedbgenarrative 等系统用户。
  • 创建 /stdb/opt/genarrative/srv/genarrative/etc/genarrative/var/lib/genarrative/maintenance
  • 安装或更新 SpacetimeDB。
  • 安装 systemd unit。
  • 安装 Nginx 配置和维护模式 snippet。
  • 执行 nginx -t
  • 启用并启动 spacetimedb.servicegenarrative-api.service

该流水线属于高风险操作,默认要求人工确认后执行。 已落地的 Jenkinsfile 为 jenkins/Jenkinsfile.production-server-provision。该流水线默认 DRY_RUN=true只打印将执行的初始化动作真正写入系统用户、目录、systemd、Nginx 配置并启动服务时,必须设置 DRY_RUN=false 且勾选 CONFIRM_PROVISION。当 DEPLOY_TARGET=release 时,还必须勾选 CONFIRM_RELEASE_DEPLOY_AGENT,并通过 linux && genarrative-release-deploy 调度到独立 release 部署 agent。

Web Build / Deploy

构建:

  • 先按 SOURCE_BRANCH / COMMIT_HASH 解析并 checkout 目标源码,默认构建 origin/master 最新 commit。
  • 构建主站静态文件。
  • 构建后台前端base path 为 /admin/
  • 生成或复制 maintenance.html
  • web/ 打包为 web.tar.gz,生成 web.tar.gz.sha256
  • 归档 web.tar.gzweb.tar.gz.sha256release-manifest.jsonweb/ 展开目录不作为 Jenkins 主归档对象。

发布:

  • 先按 SOURCE_BRANCH / COMMIT_HASH 解析并 checkout 部署脚本源码,默认使用 origin/master 最新 commit上游构建触发时使用上游传入的实际构建 commit。
  • 获取 web.tar.gzweb.tar.gz.sha256,先校验 checksum再解压到 /opt/genarrative/releases/<version>/web
  • 更新 /opt/genarrative/current/srv/genarrative/web 指向。
  • 执行 Nginx 配置测试和静态页面 smoke test。
  • 不进入维护模式。

Api Build / Deploy

构建:

  • 先按 SOURCE_BRANCH / COMMIT_HASH 解析并 checkout 目标源码,默认构建 origin/master 最新 commit。
  • 编译 Rust api-server
  • 归档单一可执行文件、必要运行说明和 release-manifest.json

发布:

  • 先按 SOURCE_BRANCH / COMMIT_HASH 解析并 checkout 部署脚本源码,默认使用 origin/master 最新 commit上游构建触发时使用上游传入的实际构建 commit。
  • 进入维护模式。
  • 解包到 /opt/genarrative/releases/<version>/api-server
  • 更新 /opt/genarrative/current
  • 重启 genarrative-api.service
  • 检查本机 /healthz
  • 导出产物归档成功后解除维护模式。
  • 失败时保留维护模式并发邮件。

Stdb Module Build / Publish

构建:

  • 先按 SOURCE_BRANCH / COMMIT_HASH 解析并 checkout 目标源码,默认构建 origin/master 最新 commit。
  • 使用 spacetime build 构建 spacetime_module.wasm
  • 归档 wasm、发布脚本和 release-manifest.json

发布:

  • 先按 SOURCE_BRANCH / COMMIT_HASH 解析并 checkout 发布脚本源码,默认使用 origin/master 最新 commit上游构建触发时使用上游传入的实际构建 commit。
  • 进入维护模式。
  • 将 wasm 上传到生产实例。
  • 在生产实例本机执行 spacetime publish -s local --bin-path spacetime_module.wasm <database-name>
  • 成功后执行必要 smoke test。
  • 成功后解除维护模式。
  • 失败时保留维护模式并发邮件。

Full Build-And-Deploy

  • 先解析一次最终 SOURCE_COMMIT,所有下游构建和发布都使用同一个分支与 commit。
  • 并行执行 Web / API / Stdb 三条构建流水线。
  • 构建全部成功后,按顺序执行 Stdb publish、API deploy、Web deploy并把同一个 DEPLOY_TARGET 透传给三条发布流水线。
  • 每条下游构建都只消费自己的归档产物,不直接复用别的 workspace。
  • 生产 Web 发布只处理 web.tar.gz 与 checksumAPI 发布只处理 api-server 与 checksumStdb 发布只处理 spacetime_module.wasm 与 checksum。

数据库导出与导入

导出

Genarrative-Database-Export 用于人工导出生产数据:

  • 已落地 Jenkinsfilejenkins/Jenkinsfile.production-database-export
  • 通过 DEPLOY_TARGET 选择逻辑导出目标;development 映射到 linux && genarrative-buildrelease 映射到 linux && genarrative-release-deploy
  • release 导出必须勾选 CONFIRM_RELEASE_DEPLOY_AGENT,避免当前开发/构建/开发部署 agent 冒充 release 部署机。
  • 进入维护模式,避免导出期间继续写入。
  • 从目标机器本机 SpacetimeDB 导出指定数据库数据,默认连接 SPACETIME_SERVER=local,自托管 root-dir 默认 /stdb
  • 产物归档到 Jenkins并可额外保存到 SERVER_BACKUP_DIRECTORY
  • 敏感 token 与 bootstrap secret 只通过 Jenkins Secret Text 凭据 ID 注入,不作为明文 Job 参数。
  • 成功后解除维护模式。
  • 失败时保留维护模式并邮件通知。

导入

Genarrative-Database-Import 用于人工导入或恢复数据:

  • 已落地 Jenkinsfilejenkins/Jenkinsfile.production-database-import
  • 通过 DEPLOY_TARGET 选择逻辑导入目标;development 映射到 linux && genarrative-buildrelease 映射到 linux && genarrative-release-deploy
  • release 导入必须勾选 CONFIRM_RELEASE_DEPLOY_AGENT,避免当前开发/构建/开发部署 agent 冒充 release 部署机。
  • 通过 INPUT_SOURCE 选择数据源,pipeline_archiveGenarrative-Database-Export 归档复制 INPUT_FILEmanual_upload 使用本次构建上传的 MANUAL_INPUT_FILE;两种方式互斥,Prepare 阶段会直接拦截混填。
  • DRY_RUN 默认开启;真正写入数据时必须勾选 CONFIRM_IMPORT,并让 CONFIRM_DATABASECONFIRM_INPUT_FILE 分别完全匹配 DATABASE 与实际输入文件。
  • REPLACE_EXISTING=trueDRY_RUN=false 时必须额外勾选 CONFIRM_REPLACE_EXISTING
  • 进入维护模式。
  • 导入前先生成一次安全备份。
  • 执行导入。
  • 执行数据校验和服务 smoke test。
  • 成功后解除维护模式。
  • 失败时保留维护模式并邮件通知。
  • pipeline_archive 模式默认使用导出流水线 Genarrative-Database-Export;只需要填写 EXPORT_BUILD_NUMBER_TO_IMPORT 时,归档输入路径自动解析为 database-exports/spacetime-migration-<导出构建号>.json。如果导出时覆盖过 WORKSPACE_EXPORT_DIRECTORYEXPORT_NAME,再显式填写归档内相对路径 INPUT_FILE
  • manual_upload 模式需要上传 MANUAL_INPUT_FILE,并在 CONFIRM_INPUT_FILE 中填写原始文件名;此模式不再填写 EXPORT_BUILD_NUMBER_TO_IMPORTINPUT_FILEEXPORT_JOB_NAME 的默认值会被忽略。
  • 敏感 token 与 bootstrap secret 只通过 Jenkins Secret Text 凭据 ID 注入,不作为明文 Job 参数。

数据库表结构变更必须同步检查并更新 migration.rs,不能只发布 wasm。

全量构建并发布

Genarrative-Full-Build-And-Deploy 编排:

  1. SOURCE_BRANCH / COMMIT_HASH 解析一次最终 SOURCE_COMMIT,默认 origin/master 最新 commit。
  2. 并行触发 Genarrative-Web-BuildGenarrative-Api-BuildGenarrative-Stdb-Module-Build,三条构建都必须使用同一个 SOURCE_BRANCHSOURCE_COMMIT
  3. 三条构建全部成功后,按顺序触发 Genarrative-Stdb-Module-PublishGenarrative-Api-DeployGenarrative-Web-Deploy,同样继续透传同一个 SOURCE_BRANCHSOURCE_COMMITDEPLOY_TARGET
  4. 最后执行生产 smoke test。

网站最后发布,避免后台或主站提前指向尚未完成发布的后端能力。

这种编排能够在不牺牲版本一致性的前提下缩短总耗时,同时避免 Web / API / Stdb 彼此等待构建资源。并行构建时仍要保证每条构建流水线独立归档自己的产物,发布阶段只能消费归档结果,不能回到构建 workspace 重新取文件。

Genarrative-Full-Build-And-Deploy 额外作为定时任务运行Jenkins 在每天凌晨 4 点自动触发一次,默认按 SOURCE_BRANCH=master 解析最新提交,并以 DEPLOY_TARGET=development 把全量构建结果部署到开发机。该定时任务不改写手动触发参数语义,只是给主线全量发布补一个固定的夜间全量刷新入口。

回滚

  • 网站回滚:将 /srv/genarrative/web/opt/genarrative/current 切回上一版本并 reload Nginx。
  • api-server 回滚:将 /opt/genarrative/current 切回上一版本并重启 genarrative-api.service
  • SpacetimeDB 模块回滚:发布上一版本 spacetime_module.wasm
  • 数据回滚:使用导入流水线恢复指定备份,必须进入维护模式。

待落地文件

后续工程落地时需要新增或改造:

  • deploy/systemd/spacetimedb.service
  • deploy/systemd/genarrative-api.service
  • deploy/nginx/genarrative.conf
  • deploy/nginx/snippets/genarrative-maintenance.conf
  • deploy/env/api-server.env.example
  • scripts/deploy/maintenance-on.sh
  • scripts/deploy/maintenance-off.sh
  • scripts/deploy/maintenance-status.sh
  • scripts/build-production-release.sh
  • scripts/jenkins-checkout-source.sh
  • scripts/deploy/production-web-deploy.sh
  • scripts/deploy/production-api-deploy.sh
  • scripts/deploy/production-stdb-publish.sh
  • jenkins/Jenkinsfile.production-web-build
  • jenkins/Jenkinsfile.production-web-deploy
  • jenkins/Jenkinsfile.production-api-build
  • jenkins/Jenkinsfile.production-api-deploy
  • jenkins/Jenkinsfile.production-stdb-module-build
  • jenkins/Jenkinsfile.production-stdb-module-publish
  • jenkins/Jenkinsfile.production-full-build-and-deploy
  • jenkins/Jenkinsfile.production-server-provision
  • 删除旧 JenkinsfileJenkinsfile.build-and-deployJenkinsfile.deployJenkinsfile.database-exportJenkinsfile.database-import
  • 更新旧部署文档,标记旧一体化脚本为废弃或迁移对象。
  • jenkins/Jenkinsfile.production-database-export
  • jenkins/Jenkinsfile.production-database-import

参考

  • SpacetimeDB 官方自托管文档:https://spacetimedb.com/docs/how-to/deploy/self-hosting/
    • 该文档建议 Ubuntu 24.04、spacetimedb 专用用户、/stdb root-dir、systemd 托管,以及 Nginx/HTTPS。
    • 默认公网路由只开放 TypeScript SDK 必需的 /v1/identity/v1/database/<database>/subscribe其他发布、SQL、管理类入口保持本机可用。