SeatFlow GitHub Actions 持续集成与发布工作流详解:单元测试、多平台发布、Dependabot 安全紧急发布
本页目录
全部文档
CI/CD 工作流
SeatFlow 使用 GitHub Actions 实现持续集成与持续发布。仓库中共有三条工作流,覆盖代码校验、多平台构建发布和安全紧急响应。
工作流总览
| 文件 | 触发条件 | 用途 |
|---|---|---|
unit-tests.yml |
Push / PR(C# 文件变更) | 增量构建 + 条件测试(含 WASM 目标校验) |
release.yml |
version.json 变更推送至 main;手动触发 |
多平台构建 → vpk 打包 → OSS 上传 → GitHub Release(含 Web 构建验证) |
dependabot-auto-release.yml |
Dependabot PR(安全类型) | 自动审批合并 → 生成发布说明 → bump 版本 → 触发发布 |
代码提交 ──→ unit-tests.yml ──→ (main, version.json) ──→ release.yml
↑
dependabot-auto-release.yml ┘ (push version.json)
1. 单元测试工作流 (unit-tests.yml)
触发条件
on:
push:
paths: ['**.cs', '**.csproj', '**.slnx', '**.axaml']
pull_request:
paths: ['**.cs', '**.csproj', '**.slnx', '**.axaml']
任何 C# 源码(.cs)、项目文件(.csproj、.slnx)或 Avalonia 标记文件(.axaml)的变更都会触发。路径过滤避免了 README 或文档变更浪费 CI 资源。
并发控制
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
同一分支/PR 上如果有新提交,旧的运行中 job 会被自动取消,节省 runner 时间。
增量测试策略
工作流使用 dorny/paths-filter@v4 实现增量测试——只运行变更相关的测试项目,而非全量测试:
| 变更路径 | 运行的测试 |
|---|---|
SeatFlow.Core/** |
Core.Tests |
SeatFlow.Infrastructure/** |
Infrastructure.Tests |
SeatFlow.Application/** |
Application.Tests |
SeatFlow.Core.Tests/** |
Core.Tests |
SeatFlow.Infrastructure.Tests/** |
Infrastructure.Tests |
SeatFlow.Application.Tests/** |
Application.Tests |
依赖传递规则:修改 Core 层会同时触发 Infrastructure 和 Application 的测试(因为上层依赖 Core)。修改 Infrastructure 层同理会触发 Application 测试。这一规则体现在 job 的条件判断中:
# Core.Tests 运行条件
- if: steps.filter.outputs.core == 'true'
|| steps.filter.outputs.infra == 'true'
|| steps.filter.outputs.tests-core == 'true'
# Infrastructure.Tests 运行条件
- if: steps.filter.outputs.core == 'true'
|| steps.filter.outputs.infra == 'true'
|| steps.filter.outputs.tests-infra == 'true'
# Application.Tests 运行条件
- if: steps.filter.outputs.core == 'true'
|| steps.filter.outputs.infra == 'true'
|| steps.filter.outputs.app == 'true'
|| steps.filter.outputs.tests-app == 'true'
执行流程
checkout (fetch-depth: 0)
→ 路径过滤 (dorny/paths-filter)
→ setup-dotnet 10.0.x
→ dotnet build (全量编译)
→ dotnet test --no-build (条件运行)
fetch-depth: 0:获取完整 git 历史,路径过滤需要 diff 信息- 先全量
dotnet build确保一致性,再--no-build运行测试避免重复编译 - Presentation 层无独立测试项目,仅参与构建验证
- 涉及浏览器目标(
net10.0-browser)的变更会安装wasm-tools工作负载并构建SeatFlow.Browser,确保 WASM 目标可编译
2. 发布工作流 (release.yml)
触发条件
on:
push:
branches: ['main']
paths: ['version.json']
workflow_dispatch:
- 自动触发:向
main分支推送version.json变更(版本号 bump) - 手动触发:通过 GitHub Actions UI 的
workflow_dispatch手动运行
并发控制
concurrency: release-${{ github.ref }}
防止同一分支同时运行多个发布流程。
Job 1: build — 多平台构建 + Velopack 打包
矩阵策略:
| RID | 运行环境 | 产物 |
|---|---|---|
win-x64 |
ubuntu-latest | SeatFlow-{ver}-Setup.exe |
linux-x64 |
ubuntu-latest | SeatFlow-{ver}-linux-x64.AppImage |
macOS 平台(osx-x64、osx-arm64)已在矩阵中注释,待后续启用。
执行步骤:
checkout → setup-python → 解析 version.json → setup-dotnet 10.0.x
→ 安装系统依赖 (squashfs-tools, zstd)
→ 安装 vpk (dotnet tool install -g)
→ dotnet publish (自包含, -r {rid})
→ vpk pack ([win]/[linux], 生成安装程序 + .nupkg + 更新源)
→ 上传 artifacts
vpk pack 关键参数:
| 参数 | Windows | Linux |
|---|---|---|
| 入口文件 | SeatFlow.exe |
SeatFlow |
| 图标 | Assets/installer.ico |
Assets/SF_icon_mini_background.png |
| 额外参数 | --noPortable |
— |
| Delta 格式 | BestSpeed (Zstandard) |
BestSpeed (Zstandard) |
Delta 格式锁定为 BestSpeed (Zstandard),因为 BestSize (bsdiff) 与客户端 Update.exe 不兼容。
产物上传:
publish/out/*.exe— Windows 安装程序publish/out/*.AppImage— Linux AppImagepublish/out/*.nupkg— NuGet 更新包publish/out/releases.*.json/publish/out/RELEASES-*— 自动更新源if-no-files-found: error— 产物缺失时报错而非静默跳过
Web 静态站(构建验证):
CI 还会安装 wasm-tools 工作负载并执行:
dotnet publish src/SeatFlow.Browser -c Release
该产物当前仅用于验证浏览器端可正常构建与发布,不随桌面安装包分发,也不部署到生产环境。
Job 2: release — GitHub Release + OSS 上传
依赖:needs: build(等待构建完成)
权限:
permissions:
contents: write # 创建 Release + 上传 assets
environment: OSS # 访问 OSS 环境级 Secrets/Vars
执行步骤:
checkout → setup-python → 解析版本 → 安装 oss2, packaging
→ 预检:
├─ 版本 Tag 已存在? → 终止
└─ 版本号 > 最新 Release? → 否则终止
→ 下载 artifacts (release-* 合并)
→ 补齐安装程序文件名中的版本号
(SeatFlow Setup.exe → SeatFlow Setup-1.4.2.exe)
→ 验证 RELEASE.md 存在
→ OSS 上传 (若凭证已配置):
├─ 校验 releases.json 版本索引
├─ 上传安装包 → releases/{version}/
├─ 上传更新包 → updates/
├─ 上传 RELEASE.md
└─ 更新 releases.json
→ 创建 GitHub Release (gh release create)
OSS 凭证预检:若 OSS_KEY_ID / OSS_KEY_SECRET / OSS_ENDPOINT / OSS_BUCKET 中任一项未配置,自动跳过 OSS 上传,仅创建 GitHub Release。
version.json 解析:两个 job 各自独立解析 version.json。build job 将版本号通过 outputs 传递给 release job,release job 使用 needs.build.outputs.version 确保版本一致。
发布触发链路
手动修改 version.json → commit → push main
→ release.yml 构建
→ GitHub Release 发布
或:
GitHub Actions UI → workflow_dispatch → release.yml
3. Dependabot 紧急安全发布 (dependabot-auto-release.yml)
触发条件
on:
pull_request:
types: [opened, reopened, synchronize, closed]
branches: [main]
监听 Dependabot PR 的完整生命周期。通过 job 级别 if 条件筛选实际执行场景。
双重守卫条件
两个 job 共享相同的核心过滤逻辑:
- PR 作者检查:
github.event.pull_request.user.login == 'dependabot[bot]'—— 仅处理 Dependabot 创建的 PR,人类 PR 不受影响 - 安全类型检测:
contains(github.event.pull_request.body, 'GHSA-')—— Dependabot 安全 PR 的 body 必然包含 GitHub 安全公告 ID(格式GHSA-xxxx-xxxx-xxxx),此条件精确区分安全更新和常规版本更新
Job 1: auto-merge — 自动审批与合并
触发时机:PR opened / reopened / synchronize(非 closed)
执行步骤:
gh pr review --approve
→ gh pr merge --auto --squash
--approve:自动化审批,绕过 "Require approvals" 分支保护规则--auto --squash:启用 GitHub 原生 auto-merge,所有 required checks 通过后自动 squash 合并- 如需绕过审批规则,需在分支保护中将
dependabot[bot]添加为例外
Job 2: prepare-release — 生成文档并触发发布
触发时机:PR closed + merged == true
执行步骤:
checkout main (含 GITHUB_TOKEN)
→ 提取 PR 元数据:
├─ PR title → 包名 + 版本范围 (如 "Bump X from 1.0 to 1.1")
└─ PR body → GHSA ID
→ 获取安全公告详情 (gh api /advisories/{GHSA})
├─ 严重等级 (Critical/High/Moderate/Low)
├─ CVSS 评分
└─ 漏洞描述
└─ API 失败时回退到 PR body 内容
→ bump version.json patch 版本 (1.4.1 → 1.4.2)
→ 读取 .github/security-release-template.md 模板
→ 替换 {placeholder} 占位符 → 写入 RELEASE.md
→ 生成标准 Keep a Changelog 条目 → 插入 CHANGELOG.md 顶部
→ commit + push 三文件 (version.json, RELEASE.md, CHANGELOG.md)
push 后的连锁反应:
prepare-release push (version.json 变更)
→ release.yml 触发
→ 完整构建 + 发布流程
安全发布模板
.github/security-release-template.md 定义了紧急安全发布的 RELEASE.md 模板,使用 {placeholder} 占位符:
| 占位符 | 填充来源 |
|---|---|
{version} |
bump 后的新版本号 |
{ghsa_id} |
PR body 正则提取 |
{ghsa_url} |
https://github.com/advisories/{ghsa_id} |
{severity_label} |
Advisory API → 中文化等级标签 |
{cvss_score} |
Advisory API → CVSS 评分 |
{package_name} |
PR title 解析 |
{from_version} / {to_version} |
PR title 解析 |
{description} |
Advisory API → 漏洞描述 |
{release_date} |
当前日期 |
{repo} |
github.repository |
模板内容包括醒目的升级提醒、漏洞信息表格、漏洞描述和升级方式说明。
CHANGELOG 自动生成
workflow 生成符合 Keep a Changelog 格式的条目,插入 CHANGELOG.md 的 # Changelog 标题行之后:
## [1.4.2] — 2026-07-25
### Security
- [GHSA-xxxx-xxxx-xxxx](https://github.com/advisories/GHSA-xxxx-xxxx-xxxx) (**CRITICAL**): 漏洞摘要
- 更新 `Package.Name` 从 1.0.0 到 1.0.1
分支保护配置
为使 Dependabot auto-merge 正常工作,需在仓库 Settings → Branches 中为 main 分支配置以下规则:
必需规则
| 规则 | 设置 | 原因 |
|---|---|---|
| Require a pull request before merging | ✅ | 所有变更必须走 PR |
| ├─ Require approvals | 1 | 人类 PR 需要审批 |
| └─ Allow bypass (指定角色) | dependabot[bot] |
Dependabot PR 免审批但仍需 CI 通过 |
| Require status checks to pass | ✅ | auto-merge 的前置条件 |
| └─ Require branches up to date | ✅ | 保证线性历史 |
推荐规则
| 规则 | 设置 |
|---|---|
| Require conversation resolution | ✅ |
| Do not allow bypassing above settings | ✅ |
| Allow deletions | ❌ |
| Allow force pushes | ❌ |
required status checks
在 Require status checks to pass 中添加 unit-tests workflow 的 job 名称。Dependabot PR 提交后,CI 通过 → GitHub 自动 squash merge → prepare-release job 触发 → bump 版本 → 自动发布。
版本号管理
release 工作流的触发依赖于 version.json 的变更。平时版本号由 scripts/version.py 管理:
# 查看当前版本
python3 scripts/version.py show
# bump 补丁版本
python3 scripts/version.py bump-app patch --force
紧急安全发布时,dependabot-auto-release.yml 自动执行 patch bump,无需人工介入。
版本号管理的完整说明见 10-version-migration.md。
环境变量与密钥
GitHub Secrets
| 密钥 | 用途 | 层级 |
|---|---|---|
OSS_KEY_ID |
阿里云 OSS AccessKey ID | Environment: OSS |
OSS_KEY_SECRET |
阿里云 OSS AccessKey Secret | Environment: OSS |
GitHub Variables
| 变量 | 用途 | 层级 |
|---|---|---|
OSS_ENDPOINT |
OSS endpoint(如 oss-cn-hongkong.aliyuncs.com) |
Environment: OSS |
OSS_BUCKET |
OSS bucket 名称 | Environment: OSS |
工作流级环境变量
env:
DOTNET_NOLOGO: 'true' # 禁用 .NET 横幅
DOTNET_CLI_TELEMETRY_OPTOUT: 'true' # 禁用遥测
PROJECT_PATH: 'SeatFlow.Desktop'
CONFIGURATION: 'Release'
手动触发发布
除了 version.json push 触发外,可以通过 GitHub Actions UI 手动触发发布:
- 进入仓库 Actions 页面
- 选择 Release SeatFlow workflow
- 点击 Run workflow
- 选择
main分支,点击 Run workflow
手动触发同样执行完整 pipeline(构建 + vpk + OSS + Release),但不会 bump 版本号——使用的是 version.json 中的当前版本。
故障排查
release.yml:vpk 命令不可用
错误信息:"dotnet tool restore" to make the "vpk" command available.
原因:仓库 dotnet-tools.json 中声明了 vpk 为本地工具,但 CI 未 restore。解决:workflow 中已使用 dotnet tool install -g vpk 全局安装,并用直接调用 vpk(而非 dotnet vpk)绕过本地 manifest 解析。
release.yml:文件未附带版本号
OSS 上传的安装程序文件名中缺少版本号(如 SeatFlow Setup.exe 而非 SeatFlow Setup-1.4.2.exe)。
原因:release.yml 曾缺失版本号补齐步骤。已通过在 "Download artifacts" 后添加 "Version installer filenames" 步骤修复——对不含版本号的文件名自动插入版本号。
dependabot-auto-release.yml:OSS 凭证为空
错误:TypeError: can only concatenate str (not "NoneType") to str
原因:OSS Secrets/Vars 未配置。已添加预检逻辑——凭证缺失时 sys.exit(0) 优雅跳过 OSS 上传,不影响 GitHub Release 创建。配置方式见 环境变量与密钥。
auto-merge 不生效
- 确认分支保护中启用了 Allow auto-merge
- 确认
dependabot[bot]已添加到 Allow specified actors to bypass required pull request approvals - 确认 required status checks 已在 PR 上通过
相关文档
- 构建与发布 (13-building-publishing.md) — 本地构建命令、发布脚本
- 版本号与迁移 (10-version-migration.md) — version.py 使用、迁移系统
- 测试指南 (12-testing.md) — 测试框架与编写规范