跳到主要内容

部署与发布

Workflow Server 可以本地开发,也可以作为自托管服务部署。生产环境建议把数据库、运行数据和文档静态文件放在明确的持久化目录中;Desktop 安装包、更新 feed 和内置项目资源由发布流水线直接写入 OSS。

环境划分

环境默认用途建议做法
开发环境本地调试 server、Desktop 和 workspace 示例*.env.example 复制本机 .env,端口可按本地环境需要调整;真实 .env 由 Git 忽略。
生产环境提供管理端、API、Embed 和 WebhookGitLab CI 使用作用域为 production 的受保护 CI/CD Variables;手工部署可使用仅存在于部署主机的 .env.production

不要把真实 .env.env.production、数据库连接串或服务密钥提交到 Git。正式 tag job 只从受保护 ref 读取 production 环境变量,并在构建前校验必需变量名;校验失败只输出缺失的变量名,不输出任何值。*.env.example 只维护变量结构和明确占位值。

断电恢复

部署主机断电后,从已认证 GitLab CLI 的 workspace checkout 执行 pnpm restore:releasepnpm restore:alpha。命令只创建并执行对应的受保护 GitLab 手动恢复 job,不会读取、写入或生成主机 .env。正式版恢复会先启动 Workflow PostgreSQL 15 和 Sub2API,再校验 stable metadata 与 main 的 Server 版本并重建 Server;随后 Docs 按已发布的精确 commit 重建并原子切换。Alpha 恢复启动同一组 Docker 服务并重启已有 current 指向的 Alpha release,不生成新的 Alpha 版本。OSS 对象不依赖部署主机,因此无需参与断电恢复。

恢复 job 会先等待所属流水线的验证 job 成功,验证失败时不会执行恢复动作。它们只使用 docker compose up -d --wait,不会执行 docker compose down -v、移除数据卷或清理持久化发布目录。恢复 job 必须运行在配置了对应 productionalpha 受保护环境变量的 Runner 上。未显式设置 DOCKER_SOCKET_LOCATION 时,job 使用 Docker daemon 标准路径 /var/run/docker.sock;需要不同挂载源时才显式设置该变量。

若 Sub2API Redis 因断电留下损坏的 AOF 尾部,恢复 job 会先在同一持久化卷中保留 AOF 备份,再使用 Redis 校验工具修复可截断的尾部并重试 Sub2API。无法通过校验修复的数据仍会使 job 失败,不会清空数据卷或静默重置 Redis。

生产环境应使用明确的持久化目录。推荐至少配置:

变量说明
WORKFLOW_RELEASE_STORAGE_ROOTServer 部署、Docs 和持久化数据的根目录。
WORKFLOW_SERVER_DATA_DIRWorkflow Server 运行数据目录;未设置时可从发布根目录派生。
WORKFLOW_DOCS_ROOT文档静态站点目录。
WORKFLOW_PUBLIC_BASE_URLWorkflow 管理端公开地址。
WORKFLOW_API_PUBLIC_BASE_URLWorkflow API 公开 HTTP(S) origin;OpenAI 调用信息优先使用该值,生产反向代理必须显式配置。
WORKFLOW_HOOKS_PUBLIC_BASE_URLWebhook 公开地址。
WORKFLOW_EMBED_PUBLIC_BASE_URLEmbed 公开地址。
WORKFLOW_DOCS_PUBLIC_BASE_URL文档站点地址。
WORKFLOW_DEPENDENCY_FETCH_TIMEOUT_MSworkflow 依赖单次下载超时;默认 3600000 毫秒。大型平台包首次安装时可按网络条件调整。
WORKFLOW_DEPENDENCY_INSTALL_TIMEOUT_MSworkflow 整体依赖安装超时;默认 3900000 毫秒。已设置 WORKFLOW_BUILD_TIMEOUT_MS 时仍可用此变量单独覆盖安装阶段。

生产启动前应确认这些目录可写、备份策略明确,并且反向代理证书覆盖对应域名。

上传 workflow 时,server 会保留包内 lockfile,并使用仓库声明的 pnpm 版本构建隔离 runtime。workflow-code@workflow-code/cli 仅用于平台 API 和开发命令,不会进入版本 runtime;项目声明的其它业务依赖会转换为不含符号链接的可移植布局,并在上传对象存储前检查归档文件类型。包含平台二进制的 SDK 可能在首次上传时下载较大的依赖包;后续相同依赖会复用 pnpm store 和 workflow runtime 缓存。若安装失败,先检查返回的 build stderr;出现下载超时时,应确认 server 到 npm registry 的网络质量、磁盘空间和上述两个超时变量。

数据库与存储

Workflow Server 直接连接 PostgreSQL 15,不经过连接池代理。仓库提供的 docker/postgres Compose 只运行 postgres:15-alpine,将宿主机 127.0.0.1:7125 映射到容器 5432;生产覆盖文件把数据绑定到 ${WORKFLOW_RELEASE_STORAGE_ROOT}/postgres-data。数据库连接串使用 WORKFLOW_DATABASE_URL,容器初始化密码使用 WORKFLOW_POSTGRES_PASSWORD

账号密码使用 Node.js 原生 scrypt 加随机盐保存。浏览器 Cookie 会话有效期 30 天,访问令牌有效期 1 小时,账号邀请链接有效期 24 小时,device code 有效期 10 分钟;数据库只保存会话和邀请 token 的 SHA-256 哈希。注销、禁用账号或修改密码会撤销对应浏览器会话。账号表为空时,第一次用 WORKFLOW_BOOTSTRAP_ADMIN_EMAILWORKFLOW_BOOTSTRAP_ADMIN_PASSWORD 登录会创建管理员账号与内置角色;之后以数据库中的当前密码和禁用状态为准。邀请链接固定进入 /account/invite/:token,新链接会使同一账号尚未使用的旧链接失效,受邀用户在该页面设置初始密码;Server 不负责发送邮件。

Workflow 版本制品和头像写入阿里云 OSS,读取直接使用 WORKFLOW_STORAGE_PUBLIC_BASE_URL 的公开域名,不使用签名 URL。写入需要受保护的 WORKFLOW_OSS_ACCESS_KEY_IDWORKFLOW_OSS_ACCESS_KEY_SECRETWORKFLOW_OSS_BUCKETWORKFLOW_OSS_REGION。对象路径为 storage/workflows/<workflow>/<version>/<hash>/{source,runtime}.tar.gzstorage/avatars/<user-id>/<hash>.<ext>。上传对象使用 public-read、正确 Content-Type 与不可变缓存头。Bucket CORS 必须支持公开 GETHEAD 和浏览器 OPTIONS 预检,允许 Range 请求并暴露长度、范围和 ETag 等响应头。

建议的检查项:

  • 数据库连接串、PostgreSQL 密码和 OSS 写入密钥只保存在服务端受保护环境变量中。
  • 上传文件、运行附件、版本包和 KV 数据都有明确备份策略。
  • 生产数据库迁移和数据修复通过受控脚本执行,不在页面或一次性终端中手工改表。
  • 只读分析工具使用只读数据库账号,不直接写入 workflow 运行表。

Server 与 Web 管理端

管理端由 Workflow Server 静态托管。常见部署流程是先构建 server 与 server web,再启动 server 进程或容器,并通过 HTTPS 反向代理暴露:

pnpm install --frozen-lockfile
pnpm build:all

启动后的健康检查应返回正常状态:

curl -i "$WORKFLOW_PUBLIC_BASE_URL/health"

响应中的 versions.serverVersionversions.coreVersion 来自当前进程加载并校验过的不可变 build info,分别表示实际运行的 Server 和内置 Core 版本。请求可使用 X-Workflow-Locale: zh-CN|en,或 ?locale=zh-CN|en,选择 currentReleasedeployment.*.releaseNotes 和 Docs 地址的语言;旧版单语言 metadata 自动回退原始 releaseNotes.body。只有 stable 发布元数据与当前 Server 构建版本一致时,currentRelease 才返回该版本的摘要、完整 Markdown 内容和 Server 发布日志中的版本锚点;deployment 保留发布存储中 Server 与 Server Web 的独立 stable 版本,便于识别部署回滚或元数据尚未同步的情况。

Server Web 会在检测到新的 Server 版本且 currentRelease 包含公开说明时展示一次更新摘要,并提供对应 Docs 记录入口。已展示的 Server 版本保存在当前浏览器;同一版本后续访问不会重复提示。

Server Web 是独立的浏览器入口,只连接 Server API,用于管理服务器项目、版本、运行记录、配置和公开 Embed;它不托管 Electron Desktop renderer,也不在浏览器中读取或执行本地项目源码。

Alpha 与正式版双部署

维护 devmain 的仓库在两者之间增加 alpha。三个分支显式声明各自的稳定 SemVer。正式版转正后先建立连续基线,例如 main0.1.20alpha0.1.21dev0.1.22;此后每次真实 Alpha 发布都把 alphadev 各增加一个 patch,因此再次发布时可变为 main 0.1.20alpha 0.1.22dev 0.1.23。常态约束是 main < alpha < devdev = alpha + 1 patch,不要求尚未转正的 alpha 永远只比 main 高一个 patch。Alpha CI 使用该分支的新声明版本,并追加上海时区日期和当天三位序号,例如 0.1.22-20260826001。Server 与 Server Web 在 Alpha 通道共用同一个版本;每个仓库的 Alpha tag、GitLab artifact 和本机制品只保留最新三个可用版本。

Alpha Server 与正式版必须复用同一组 WORKFLOW_DATABASE_URLWORKFLOW_OSS_ACCESS_KEY_IDWORKFLOW_OSS_ACCESS_KEY_SECRETWORKFLOW_OSS_BUCKETWORKFLOW_OSS_REGIONWORKFLOW_STORAGE_PUBLIC_BASE_URL。账号、项目、版本记录、KV 和对象存储因此是同一份业务数据,不进行双写或异步同步。两套运行实例只隔离以下内容:

项目正式版Alpha
HTTP 端口71307140
发布通道stablealpha
代码和静态资源正式发布目录deployments/server/alpha/releases/<version>
当前版本指针正式版指针deployments/server/alpha/current
PID 与日志正式版运行目录deployments/server/alpha/run
本地缓存和 runtime 数据正式版数据目录server-data/alpha
自动计划轮询开启关闭

Alpha 进程固定覆盖以下运行值;其它数据库和存储凭据沿用正式版:

WORKFLOW_RELEASE_CHANNEL=alpha
WORKFLOW_SERVER_PORT=7140
WORKFLOW_SERVER_DATA_DIR=/srv/workflow-release/server-data/alpha
WORKFLOW_SCHEDULE_POLLING_ENABLED=false

Alpha 关闭自动计划轮询,避免两套进程从共享数据库重复领取同一个计划。计划查询、编辑和手工“立即运行”仍然可用,正式版继续作为唯一自动调度实例。Alpha 相对 main 的数据库变更只允许增加表、列或索引;删除、重命名、收紧非空约束和其它破坏性 DDL 会在部署前被门禁拒绝。

GitLab Alpha 环境

在 Core、CLI、Shared、Server、Desktop 和 workspace 项目中保护 alpha 分支与 alpha/v* tag,并为 alpha environment 配置受保护、掩码的变量:

变量用途
WORKFLOW_ALPHA_SYNC_TOKEN跨项目推送 Alpha 依赖和 workspace 快照、创建或清理 Alpha tag、清理旧 job artifact。需要对应项目的仓库写入和 API 权限。
WORKFLOW_SHARED_SYNC_TARGETSShared 下游项目路径列表,使用逗号或换行分隔 Core、CLI、Server 和 Desktop。
NPM_TOKENCore 与 CLI 发布 npm alpha dist-tag;必须允许发布对应包。
WORKFLOW_RELEASE_STORAGE_ROOTServer Alpha 部署使用的绝对发布根目录。
WORKFLOW_ALPHA_PUBLIC_URLAlpha Server 的 HTTPS 地址,例如 https://wfalpha.yuhe.space,用于发布后外部健康检查。

数据库、PostgreSQL、OSS、认证和运行时所需变量也要在 alpha environment 中配置,值与 production 相同。不要只把这些变量限定为 production,否则 Alpha job 无法读取。跨项目 token 必须能够推送全部 Alpha 仓库和 workspace;若使用 CI_JOB_TOKEN,需要逐项目开启 job token allowlist 和目标分支写入权限。

DNS 与反向代理

将 Alpha 域名解析到与正式版相同的部署入口,再把 Alpha Server 单独代理到本机 7140。以下 Nginx 片段展示关键边界,证书、日志和安全 header 继续复用现有站点配置:

server {
listen 443 ssl;
server_name wfalpha.yuhe.space;

location / {
proxy_pass http://127.0.0.1:7140;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

Desktop Alpha feed 和安装包由 OSS 提供,不需要在 Server 反向代理中配置 /desktop/alpha/。上线和每次发布后至少执行:

dig +short wfalpha.yuhe.space
sudo nginx -t
curl --fail --show-error https://wfalpha.yuhe.space/health
curl --fail --show-error https://wfupdates.yuhe.space/desktop/alpha/latest-mac.yml
curl --fail --show-error https://wfupdates.yuhe.space/desktop/alpha/latest.yml

健康响应中的 Server 版本应等于当前 Alpha 版本,deployment.server.tagdeployment.serverWeb.tag 应使用同一个 alpha/v... tag。发布主机还应确认 7140 只有一个 Alpha 进程、7130 正式版健康、Alpha 计划轮询已关闭,并且 Alpha feed 中 macOS 与 Windows metadata 引用的文件都可下载。

OSS 中的内置项目 index.json 和兼容用 manifest.json 是可变元数据,必须返回 Cache-Control: no-cache, no-transform, must-revalidatevX.Y.Z/ 下的哈希校验资源应返回 Cache-Control: public, max-age=31536000, immutable。发布后可用以下命令复核:

curl -fsSI https://wfupdates.yuhe.space/builtin-projects/conversation/index.json | grep -i '^cache-control:'
curl -fsSI 'https://wfupdates.yuhe.space/builtin-projects/conversation/v0.1.4/conversation-universal.tgz' | grep -i '^cache-control:'

可选 Sub2API 服务

仓库提供独立的 Sub2API Compose 配置,用于部署 Wei-Shaw/sub2api AI API 网关。该服务不与 Workflow Server 共用数据库或 Redis,默认只在本机 127.0.0.1:7134 提供管理界面和 API:

pnpm deploy:sub2api
curl --fail --show-error http://127.0.0.1:7134/health

手工开发可从 docker/sub2api/.env.example 复制被忽略的 docker/sub2api/.env。GitLab 正式 job 直接从 production 环境的受保护 CI/CD Variables 注入数据库、Redis、管理员、JWT 和 TOTP 配置,不生成或提交生产 env 文件。正式部署前应轮换这些密钥;需要外部访问时,应继续保持本机端口绑定并通过具有 HTTPS 和访问控制的反向代理公开服务。PostgreSQL 与 Redis 只连接 Compose 私有网络,不应额外暴露宿主机端口。

Workflow Server 需要管理 Sub2API 用户时,在 Server 进程环境中配置:

变量说明
WORKFLOW_SUB2API_BASE_URLSub2API 服务地址;同一宿主机进程可使用 http://127.0.0.1:7134
WORKFLOW_SUB2API_ADMIN_API_KEYSub2API 生成的 admin- 前缀管理密钥,只允许 Server 进程读取。
WORKFLOW_SUB2API_PROXY_SECRET用户 AI 代理短凭据的 HMAC-SHA256 签名密钥。未配置时依次回退到 WORKFLOW_AUTH_COOKIE_SECRETWORKFLOW_SERVER_ADMIN_KEY;生产环境建议独立配置和轮换。
WORKFLOW_SUB2API_REQUEST_TIMEOUT_MSServer 调用 Sub2API 管理接口的超时,默认 10000 毫秒。
WORKFLOW_SUB2API_GROUP_CACHE_TTL_MSSub2API 分组读取的进程内缓存时间,默认 60000 毫秒;设为 0 可关闭。
WORKFLOW_SUB2API_SUBSCRIPTION_CACHE_TTL_MS管理员订阅分页读取的进程内缓存时间,默认 10000 毫秒;设为 0 可关闭。
WORKFLOW_SUB2API_USER_STATE_CACHE_TTL_MS用户绑定状态、账户余额、用户订阅、API Key 和余额分组用量的进程内缓存时间,默认 10000 毫秒;设为 0 可关闭。
WORKFLOW_SUB2API_CACHE_STALE_TTL_MS只读缓存过期后的临时故障兜底窗口,默认 300000 毫秒;设为 0 可关闭。仅网络错误、超时、限流和 5xx 会使用旧值,强制刷新与 401/403/404 不会降级。

Server 和 Sub2API 都运行在容器中时,应把它们加入同一受控 Docker 网络,并把服务地址改为 Sub2API 的 Compose 服务名与容器端口。Admin API Key 不应放入浏览器配置、workflow 项目环境变量、公开日志或客户端响应。

短期缓存只存在于 Workflow Server 进程内。缓存到期后 Server 会先请求 Sub2API;遇到临时连接故障时,可以在 stale 窗口内继续返回最后一次成功的只读结果。充值、退款、订阅撤销、Key 启停和其它写入仍实时执行,成功后立即清除对应的新鲜值与 stale 值;重启 Server 也会清空全部缓存。

用户 workflow 不直接连接 Sub2API。GET /api/auth/sub2api/llm-credentials 只向具有用户身份的调用方签发一小时代理凭据,Core 在本地闭包中保存并提前 60 秒刷新。模型调用只能进入 Workflow Server 的 /api/auth/sub2api/llm-proxy/v1/messages/v1/responses/v1/chat/completions 三条固定路径;Server 会移除客户端认证、Cookie 和逐跳 header,再注入实际分组 Key。普通 JSON 与 SSE 都按流转发,客户端断开时取消上游请求,请求体上限为 50 MiB。

Server resolver/run 子进程不使用一小时用户 token,而是获得只在该子进程存活期间有效的 wfrt_ capability。只有账号会话或账号 API Key 对应的 actor 可以获得 capability;匿名 Embed、Webhook 和不带用户身份的管理员 Key 不具备该能力。子进程退出时 capability 会立即撤销。

上述有界缓存只保存在当前 Server 进程内,不会把 Sub2API 订阅、余额、额度、用量、绑定状态、API Key 或分组明细复制到 Workflow Server 数据库。相同缓存键的并发读取会合并为一次上游请求;显式绑定校验、订单支付、分组启用和退款仍直接读取 Sub2API,绑定、解绑、充值、分配、续期、撤销和密钥写入成功后会立即失效相关缓存。代理使用的完整分组 Key 也只进入有界短缓存,Sub2API 网关仍执行最终 Key 状态校验。多实例部署时,各实例独立维护缓存,因此缓存只用于降低读取延迟,不能作为业务状态来源。

停止服务但保留数据时运行:

pnpm deploy:sub2api:down

应用、数据库和 Redis 均使用 Docker 命名卷持久化。升级 SUB2API_IMAGE 或清理命名卷前,应先完成数据库和应用数据备份。

本机发行入口与可选远程模式

从仓库根目录运行以下命令,可以更新生产工作副本并完成指定服务的构建、重启和本机健康检查:

pnpm release:server
pnpm release:server-web
pnpm release:database
pnpm release:doc

当前正式流水线的 Server、Server Web 和 Docs job 与目标服务位于同一部署主机,并设置 WORKFLOW_SERVER_RELEASE_LOCAL=true。本地模式直接执行同一份事务脚本,以 candidate checkout 的本地 Git 地址同步生产工作副本,不解析 SSH 凭据,也不调用 sshscp。tag 流水线仍会传入受保护 tag 与 commit,构建前验证 tag 指向并以 detached HEAD 检出该 commit,避免发布过程中读取更新后的分支。

在部署主机手动运行时,也可以设置 WORKFLOW_SERVER_RELEASE_LOCAL=true。需要从其它 Windows、macOS 或 Linux 设备运维时,省略该变量,并使用 WORKFLOW_SERVER_RELEASE_HOSTWORKFLOW_SERVER_RELEASE_PORTWORKFLOW_SERVER_RELEASE_USERWORKFLOW_SERVER_RELEASE_REMOTE_ROOTWORKFLOW_SERVER_RELEASE_REMOTE_REPOWORKFLOW_SERVER_RELEASE_BRANCHWORKFLOW_SERVER_RELEASE_SSH_KEY 配置兼容的远程模式。正常执行会持续输出 Git、安装、构建和健康检查进度;追加 -- --dry-run 只输出脱敏配置与待执行脚本。两种模式都只更新 Git 跟踪文件,不清理生产工作副本中的未跟踪配置。

Server 与 Server Web 发布使用仓库固定的 Node.js 版本和 packageManager 中的精确 pnpm 版本。联合转正时先完成 server/vX.Y.Z,再在同一 commit 创建 server-web/vX.Y.Z;后一个 tag 流水线会先核对两个 tag 的 commit,再原子激活包含 Server 与 Server Web 的正式部署。新产物会在旧服务仍可用时完成构建;切换后依次验证本机进程、双份 stable metadata 和公开健康端点。构建、启动、健康检查或 metadata 发布任一步失败时,流水线都会恢复旧指针、旧 metadata 与旧进程。同一版本因此可以直接重试失败 job,不需要仅为重试再次提升版本。

release:doc 会先从持久化 release metadata 重新生成发布总览、下载、兼容关系和完整更新记录,再生成使用公开 API 地址的不可变 Docs source。新 source 会先在独立预检端口启动并等待首页返回 HTTP 200,此时旧站点继续提供服务;预检成功后才切换正式端口。正式切换或部署记录写入失败时,发行命令会从上一次部署记录中的 source 恢复旧站点。部署记录通过临时文件原子替换,并包含 commit、branch、tag、source 和部署时间,供后续发布与故障恢复使用。

分支与自动发布

仓库使用 dev 作为日常集成分支、alpha 作为自动测试发布分支,main 只接收经过 Alpha 验证的正式发布。普通功能变更先写入 dev 的中英文 CHANGELOG.next*。准备新 Alpha 时,先在两个渠道分别把当前 next 的非空内容手动归档到旧声明版本的历史条目,再把 next 恢复为仅含 # Unreleased;随后将 alphadev 的声明版本各增加一个 patch,并让版本准备提交跳过 CI。不能用正式 release:prepare 代替这一步,因为它还会准备稳定依赖和其它正式发布文件。

版本与日志准备完成后,把 dev 内容合入 alpha,保留目标 Alpha 版本,同时在冲突处理中保留旧 Alpha 与旧 Dev 两个历史条目,并让合并后的 next 继续为空。这样新声明版本的 next 只记录版本预留之后的新变化,不会重复携带上一个版本的说明。Alpha CI 只在临时构建目录中追加日期序号;Desktop 的日期版发布说明读取与 X.Y.Z-YYYYMMDDNNN 对应的 X.Y.Z 历史条目,而不是读取已清空的 next。

Alpha 转正时,从已验证的精确 Alpha 提交创建正式候选,在候选上执行 release:prepare、把日期版依赖收敛为稳定依赖,并直接合入 main,不再经过 dev 或重新触发 Alpha。正式准备会归档候选版本的双语日志并恢复空的 next。正式发布成功后,仅把 alpha 版本初始化为 main + 1 patch、把 dev 初始化为 alpha + 1 patch,版本基线提交跳过 CI,避免发布没有业务变化的空 Alpha;任一步失败都必须恢复全部文件。

GitLab 项目需要完成以下保护设置:

  • dev 设为默认开发分支,并禁止直接删除。
  • alpha 设为受保护分支,只允许通过 dev -> alpha MR 或发布账号的依赖级联提交更新。
  • main 设为受保护分支,只允许通过经过审批和验证的发布 MR 合入。
  • 保护 alpha/v* tag,只允许 Alpha 发布账号创建和按三版本保留策略清理。
  • 分别保护 workflow-code/v*workflow-code-cli/v*server/v*server-web/v*desktop/v* tag;保护规则同时覆盖 commit 固定的 candidate tag 和最终正式 tag,只允许发布账号创建。
  • 配置受保护且掩码的 RELEASE_GITLAB_TOKEN CI 变量。该 token 只授予当前项目创建 tag、读取 pipeline 和重试 pipeline 所需的 API 权限,不用于 npm、服务器 SSH 或 Desktop 签名。
  • 为原生 Windows 构建机注册受保护 runner,并配置 windows 标签;若 GitLab 实例还托管其它项目,建议使用项目级 runner 限制使用范围。runner 需要提供 Git、Windows PowerShell 和可启动构建脚本的 Node;实际 Desktop 构建仍会切换到仓库固定的 Node/pnpm 工具链。

main 流水线先分析本次合入的路径影响,再以 package 版本相对 stable metadata 和正式 tag 的增量生成发布计划。组件代码有变化但版本没有提升、历史日志缺少对应版本、next 日志仍有未消费条目、CLI peer range 不包含当前 Core,或同名正式 tag 指向其它 commit 时,流水线会在开始发布前失败。路径只负责发现受影响组件,正式发布始终由已经准备好的版本触发。

同一次发布涉及多个单元时,流水线按照 Core、CLI、Server、Server Web、Desktop 的顺序每次只创建一个受保护 candidate tag。candidate 名称包含目标版本和 commit,构建/发布、Docs 部署和正式 tag finalize 使用依赖串行的独立任务,失败时只重试失败任务及其下游任务。metadata 尚未写入时,即使需要修复代码也可保留原产品版本,新 commit 会产生新的 candidate;metadata 写入后版本已绑定原 commit,流水线只重试 Docs 或 finalize,不会重复生成新版本。全部完成后才推进下一个发布单元,并将 main fast-forward 同步回 dev

Desktop candidate 会由 windows runner 和 macmini 分别构建 Windows x64 与 macOS 安装包。两个平台作业直接并行上传带大小和 SHA-256 元数据的版本化 OSS 对象,只把小型清单交给汇总作业;汇总作业校验版本与完整 commit 后,通过 OSS 服务端复制生成固定下载名,并最后切换 latest*.yml。任一平台产物缺失或身份不一致时发布立即失败。

Core 与 CLI 的 npm 发布只有在公共 registry 回读到与本地 tarball 相同的 SHA-512 integrity 后才算成功。客户端超时或返回冲突时,流水线仍会先执行同一回读,因此 registry 已接收的相同包可以幂等恢复;同版本内容不同则直接拒绝。所有单元的 version、stable 和聚合 index metadata 会先在同一存储卷暂存,再带备份切换;任一切换失败都会恢复旧文件,旧 candidate 也不能把 stable 倒退到较低版本。

Docs 不维护产品版本。只有 docs/** 或 Docs 生成器变化且没有组件待发布时,main 流水线才直接部署 Docs,并固定检出触发流水线的 commit。部署成功后,部署记录会保存 commit、branch、tag、source 和时间;组件发布仍在 metadata 成功后重新生成并部署 Docs。

下载与更新服务

Desktop 与五个内置项目的发布资源统一存放在公共读、凭据写的 OSS bucket。wfdownload.yuhe.space 提供手动安装包,wfupdates.yuhe.space 提供更新 feed 和内置项目索引;两个域名可以指向同一个 bucket,不再经过 Server、macmini Nginx 或本地缓存目录。

Desktop 和内置项目的 GitLab production 环境需要配置受保护、掩码的 WORKFLOW_OSS_ACCESS_KEY_IDWORKFLOW_OSS_ACCESS_KEY_SECRET。Desktop 的 alpha 环境也需要相同变量。bucket、region 与两个公开域名由 CI 中的 WORKFLOW_OSS_BUCKETWORKFLOW_OSS_REGIONWORKFLOW_OSS_DOWNLOAD_BASE_URLWORKFLOW_OSS_UPDATES_BASE_URL 声明,可由项目级变量覆盖。写入 Key 只授予目标 bucket 的对象读写权限,不放入仓库、安装包或运行时配置。

版本化安装包和资源不可覆盖,并使用长期缓存;latest*.ymlrelease.jsonmanifest.jsonindex.json 使用重新验证缓存策略,且只在全部资源校验成功后最后更新。发布后应同时验证公开 HEAD、Range 下载、对象大小和 SHA-256 元数据。

macOS 自动更新要求 Desktop 位于可写的 /Applications~/Applications,并且后续版本保持一致的代码签名身份。Windows x64 自动更新读取 latest.yml、NSIS 安装程序和对应 blockmap;启用前应确认已安装 Desktop 可以完成检查、下载和重启安装,受系统策略限制时保留手动覆盖安装路径。

文档站点

文档发布前会把源码 OpenAPI 中的默认 server 地址替换为公开 API 地址。这样本地开发仍可使用本地地址,而发布后的 API Playground 默认请求你的生产 API。

发布后建议检查:

  • 文档站点首页和导航页面可正常打开。
  • OpenAPI Playground 默认请求你的公开 API 域名。
  • Desktop 下载、服务端入口和 API 入口链接指向同一套部署环境。