使用 go:embed 嵌入迁移 SQL 到二进制,移除 runtime.Caller 源码路径依赖, server 和 desktop 发布产物均可在无源码目录环境下完成数据库初始化和迁移。
13 KiB
发布流水线
Purpose
定义 tag 驱动的发布流程、跨平台构建产物要求与 Draft Release 组装规则,确保发布结果可复现且可审阅。
Requirements
Requirement: Tag 驱动发布流水线
系统 SHALL 仅在符合 vX.Y.Z 格式的 Git tag 上触发发布流水线,普通分支 push SHALL NOT 创建发布。发布流水线 SHALL 使用 ./versionctl 而非 ./backend/cmd/versionctl 调用版本管理工具。
Scenario: 有效发布 tag
- WHEN 仓库收到
v1.2.3tag push - THEN 发布流水线 SHALL 启动版本校验、构建和 Release 组装步骤
- AND 版本校验步骤 SHALL 使用
go run ./versionctl print和go run ./versionctl verify-tag获取并验证版本
Scenario: 普通分支推送
- WHEN 仓库收到非 tag 的分支 push
- THEN 系统 SHALL NOT 创建 GitHub Release
Requirement: 发布流水线 Go 模块缓存覆盖
发布流水线 SHALL 在所有 Go module 的 go.sum 文件存在时正确设置 Go 模块缓存路径,确保新增的 versionctl module 依赖也被缓存。
Scenario: CI 缓存覆盖所有 module
- WHEN 发布流水线设置 Go 模块缓存
- THEN
cache-dependency-pathSHALL 覆盖backend/go.sum和versionctl/go.sum
Requirement: 三平台发布构建
系统 SHALL 在发布流水线中构建 server、web 与 desktop 的发布产物,并覆盖 Linux、Windows、macOS 的目标架构和格式矩阵。
Scenario: server 发布构建
- WHEN 发布流水线执行 server 发布构建
- THEN 系统 SHALL 生成
nex-server_<version>_linux_amd64.tar.gz - AND 系统 SHALL 生成
nex-server_<version>_linux_arm64.tar.gz - AND 系统 SHALL 生成
nex-server_<version>_macos_amd64.tar.gz - AND 系统 SHALL 生成
nex-server_<version>_macos_arm64.tar.gz - AND 系统 SHALL 生成
nex-server_<version>_macos_universal.tar.gz - AND 系统 SHALL 生成
nex-server_<version>_windows_amd64.zip
Scenario: web 发布构建
- WHEN 发布流水线执行 web 发布构建
- THEN 系统 SHALL 使用 Bun 构建
frontend/dist - AND 系统 SHALL 将前端静态资源打包为
nex-web_<version>.tar.gz - AND server 发布资产 SHALL NOT 内置 Web 管理界面静态资源
Scenario: Linux desktop 发布构建
- WHEN 发布流水线执行 Linux desktop 发布构建
- THEN 系统 SHALL 在可访问 Go、Bun、CGO、GTK3、Ayatana AppIndicator 和 Linux 打包工具链的环境中构建
- AND 系统 SHALL 为
amd64和arm64分别生成 tar.gz、AppImage、deb 和 rpm desktop 发布资产 - AND Linux amd64 desktop 发布构建 SHALL 在
ubuntu-latestrunner 上执行 - AND Linux arm64 desktop 发布构建 SHALL 在
ubuntu-24.04-armrunner 上执行 - AND 系统 SHALL NOT 在构建步骤中显式传递 TARGET_ARCH 参数
Scenario: Windows desktop 发布构建
- WHEN 发布流水线执行 Windows desktop 发布构建
- THEN 系统 SHALL 在包含对应架构 MSYS2/MinGW 或等价 CGO 工具链的环境中构建
- AND Windows amd64 desktop 发布构建 SHALL 在
windows-latestrunner 上的 MSYS2 MINGW64 环境中执行 - AND 系统 SHALL 生成
nex-desktop_<version>_windows_amd64.zip - AND 系统 SHALL NOT 在构建步骤中显式传递 TARGET_ARCH 参数
Scenario: macOS desktop 发布构建
- WHEN 发布流水线执行 macOS desktop 发布构建
- THEN 系统 SHALL 在可访问 Go、Bun、Xcode 命令行工具、
lipo、hdiutil和 zip 打包工具的 macOS 环境中构建 - AND 系统 SHALL 在 ARM64 macOS runner 上编译 amd64 和 arm64 双架构二进制并使用
lipo合并为 universal binary - AND 系统 SHALL 生成
nex-desktop_<version>_macos_universal.zip - AND 系统 SHALL 生成
nex-desktop_<version>_macos_universal.dmg
Scenario: 原生架构构建
- WHEN 发布流水线执行 Linux 或 Windows 的 server/desktop 构建步骤
- THEN 系统 SHALL NOT 显式传递 TARGET_ARCH 参数
- AND Makefile SHALL 通过
go env GOARCH自动检测目标架构 - AND 原生 runner 的实际架构 SHALL 与
go env GOARCH返回值一致
Requirement: 三平台发布构建预检
系统 SHALL 在正式执行各平台 release 构建前验证对应 job 的关键工具链可用性,并在环境不完整时快速失败且输出明确诊断。
Scenario: Linux 预检通过后开始构建
- WHEN Linux 发布 job 中的
go、bun、gcc、pkg-config、GTK3、Ayatana AppIndicator 和 Linux 打包工具均可用 - THEN 系统 SHALL 输出关键工具的版本信息或解析路径
- AND 系统 SHALL 继续执行对应 Linux release 构建
Scenario: Windows 预检通过后开始构建
- WHEN Windows 发布 job 中的
go、bun、make、对应架构 CGO 编译器和 resource 生成工具均可用 - THEN 系统 SHALL 输出关键工具的版本信息或解析路径
- AND 系统 SHALL 继续执行对应 Windows release 构建
Scenario: macOS 预检通过后开始构建
- WHEN macOS 发布 job 中的
go、bun、ditto、lipo、vtool和hdiutil均可用 - THEN 系统 SHALL 输出关键工具的版本信息或解析路径
- AND 系统 SHALL 继续执行对应 macOS release 构建
Scenario: web 预检通过后开始构建
- WHEN web 发布 job 中的
bun和前端构建依赖均可用 - THEN 系统 SHALL 输出 Bun 版本信息
- AND 系统 SHALL 继续执行 web release 构建
Scenario: 任一预检发现工具缺失
- WHEN 任一发布 job 中存在关键工具不可用
- THEN 发布流水线 SHALL 在正式构建前失败
- AND 系统 SHALL 在日志中标识缺失的工具链名称
Requirement: 发布流水线 LFS 资产拉取
发布流水线 SHALL 在所有会 checkout 仓库并参与版本校验、web 构建、server 构建或 desktop 构建的 job 中拉取 Git LFS 真实文件,确保发布构建读取到真实二进制资产而非 LFS pointer 文本。
Scenario: 发布 job 获取真实 LFS 图标资产
- WHEN 发布流水线执行任一参与版本校验、web 构建、server 构建或 desktop 构建的 job 的 checkout 步骤
- THEN checkout 步骤 SHALL 拉取 Git LFS 文件
- AND
assets/icon.ico、assets/icon.icns、assets/icon.png和frontend/public/icon.pngSHALL 在后续步骤中表现为真实图标文件而非 LFS pointer 文本
Scenario: 新增矩阵 job 获取真实 LFS 资产
- WHEN 发布流水线新增 server、web、desktop、platform 或 arch 矩阵 job
- THEN 该 job 的 checkout 步骤 SHALL 使用与现有发布 job 一致的 Git LFS 拉取配置
Requirement: 发布资产图标预检
发布流水线 SHALL 在正式执行任何需要图标资产、前端 public 图标或 desktop 打包资源的发布构建前校验关键图标资产可用,并在检测到 LFS pointer 或错误格式时快速失败且输出明确诊断。
Scenario: 图标资产为 LFS pointer
- WHEN 发布资产预检发现关键图标文件内容为 Git LFS pointer 文本
- THEN 发布流水线 SHALL 在执行对应 release 构建前失败
- AND 系统 SHALL 在日志中标识对应图标文件需要拉取 Git LFS 真实内容
Scenario: 图标资产格式无效
- WHEN 发布资产预检发现关键图标文件不是对应格式的有效资源
- THEN 发布流水线 SHALL 在执行对应 release 构建前失败
- AND 系统 SHALL 在日志中标识格式无效的图标文件路径
Scenario: 图标资产预检通过
- WHEN
assets/icon.ico、assets/icon.icns、assets/icon.png和frontend/public/icon.png均为真实且格式可用的图标资产 - THEN 发布流水线 SHALL 继续执行依赖这些资产的 release 构建
Requirement: 发布流水线运行时兼容性
系统 SHALL 保持与 GitHub-hosted runner 当前受支持的 workflow runtime 约束兼容,避免发布流程依赖已声明弃用的 runtime 或执行约束。
Scenario: runner runtime 升级前完成兼容更新
- WHEN GitHub-hosted runner 宣布 workflow runtime 或关键执行约束将从旧版本迁移到新版本
- THEN 发布流水线 SHALL 在旧约束移除前完成兼容性更新
Scenario: 发布流水线执行时不依赖已弃用 runtime
- WHEN 发布流水线运行 release workflow
- THEN 关键发布步骤 SHALL NOT 依赖已被 GitHub-hosted runner 标记为待移除的 runtime 或执行约束
Requirement: 版本化发布资产命名
系统 SHALL 为 server、web 与 desktop 发布资产使用包含统一版本号、组件、目标平台和目标架构信息的文件名,确保 Release 页面可直接区分产物用途、平台、架构和格式。
Scenario: server 资产命名
- WHEN 当前发布版本为
1.2.3 - THEN Linux server 发布资产文件名 SHALL 为
nex-server_1.2.3_linux_amd64.tar.gz和nex-server_1.2.3_linux_arm64.tar.gz - AND macOS server 发布资产文件名 SHALL 为
nex-server_1.2.3_macos_amd64.tar.gz、nex-server_1.2.3_macos_arm64.tar.gz和nex-server_1.2.3_macos_universal.tar.gz - AND Windows server 发布资产文件名 SHALL 为
nex-server_1.2.3_windows_amd64.zip
Scenario: web 资产命名
- WHEN 当前发布版本为
1.2.3 - THEN web 发布资产文件名 SHALL 为
nex-web_1.2.3.tar.gz - AND web 发布资产文件名 SHALL NOT 包含平台或架构字段
Scenario: desktop 资产命名
- WHEN 当前发布版本为
1.2.3 - THEN Linux desktop 发布资产文件名 SHALL 使用
nex-desktop_1.2.3_linux_<arch>.<format>格式 - AND Windows desktop 发布资产文件名 SHALL 为
nex-desktop_1.2.3_windows_amd64.zip - AND macOS desktop 发布资产文件名 SHALL 为
nex-desktop_1.2.3_macos_universal.zip和nex-desktop_1.2.3_macos_universal.dmg - AND 发布资产文件名中的 macOS 平台字段 SHALL 使用
macos而非darwin
Requirement: Draft Release 组装
系统 SHALL 将发布流水线产物上传到 GitHub Draft Release,由人工确认后再公开发布,并 SHALL 生成覆盖全部发布资产的校验和清单。
Scenario: 发布成功时创建 Draft Release
- WHEN 版本校验通过且 server、web、desktop 的全部目标发布资产构建完成
- THEN 系统 SHALL 创建或更新与该 tag 对应的 GitHub Draft Release
- AND 系统 SHALL 上传 server、web 与 desktop 的全部发布资产
- AND 系统 SHALL 上传
SHA256SUMS
Scenario: 校验和覆盖全部资产
- WHEN Draft Release 组装步骤生成
SHA256SUMS - THEN
SHA256SUMSSHALL 包含除自身以外的全部发布资产文件 - AND
SHA256SUMS中的文件名 SHALL 与实际上传的 release asset 文件名一致
Scenario: 构建失败时阻止完成发布
- WHEN 任一目标发布资产构建失败、打包失败、校验失败、artifact 上传为空或版本校验失败
- THEN 发布流水线 SHALL 失败
- AND 系统 SHALL NOT 产生可直接公开的成功发布结果
Scenario: artifact 缺失时快速失败
- WHEN 任一构建 job 尝试上传 release artifact 但匹配不到目标文件
- THEN 该 job SHALL 失败
- AND Draft Release 组装 SHALL NOT 继续发布不完整资产集合
Requirement: 发布产物运行时资源完整性
发布流水线 SHALL 确保 server 和 desktop 发布产物包含运行时启动所需的数据库迁移资源,且 SHALL NOT 依赖 CI runner 的源码路径。
Scenario: desktop 发布产物包含迁移资源
- WHEN 发布流水线构建 desktop 发布资产
- THEN 生成的 desktop 二进制或应用包 SHALL 包含 SQLite 和 MySQL 迁移资源
- THEN macOS
.app、.zip和.dmg安装后 SHALL 不需要仓库源码目录即可执行启动迁移
Scenario: server 发布产物包含迁移资源
- WHEN 发布流水线构建 server 发布资产
- THEN 生成的 server 二进制 SHALL 包含 SQLite 和 MySQL 迁移资源
- THEN server 发布资产 SHALL 不需要仓库源码目录即可执行启动迁移
Scenario: 发布产物不泄漏构建机迁移路径
- WHEN 发布流水线完成 server 或 desktop 构建
- THEN 构建产物 SHALL NOT 在运行时使用
/Users/runner/work/.../backend/migrations/...作为迁移目录 - THEN 若检测到运行时迁移路径依赖 CI runner 源码路径,发布构建 SHALL 失败
Scenario: 发布构建迁移资源验证
- WHEN 发布流水线执行 release 构建验证
- THEN 验证 SHALL 覆盖迁移资源可用性
- THEN 验证 SHALL 覆盖安装包内应用在无源码目录环境下可解析迁移资源
- THEN 验证 MAY 通过 Go 测试或轻量资源自检完成,不要求启动图形托盘界面