开发发布流程¶
本文档定义 Telegram Panel 从功能开发到主分支发布的唯一流程。目标是让 dev 成为可部署、可验收的集成环境,让 main 只接收已经完成云端验证的代码。
分支职责¶
main:稳定主分支,生产镜像和正式文档从这里发布。dev:集成和云端测试分支,推送后构建ghcr.io/moeacgx/telegram-panel:dev-latest。codex/<purpose>:临时功能分支。完成合并后删除本地分支、远端分支和对应临时 worktree。
不使用历史版本分支、临时 merge 分支或长期个人分支承载发布状态。
标准流程¶
1. 开发与文档¶
开始前记录当前分支和工作区状态。重要改动必须同步开发文档,具体门禁见 文档维护 和根目录 AGENTS.md。
提交前至少确认:
- 功能行为、API、配置和部署方式已经在对应文档中说明;
- 文档写明前置条件、验证步骤、失败排查和回滚方式;
- 测试覆盖新增行为和关键回归场景;
mkdocs.yml已包含新增文档页面。
2. 合并到 dev¶
功能分支完成本地验证后,推送到远端并通过 PR 合并到 dev。没有云端验收结果时,不得合并到 main。
当前仓库的 Docker 工作流 .github/workflows/docker.yml 在 dev 推送后会构建并推送:
ghcr.io/moeacgx/telegram-panel:dev-latest
dev 默认只构建 linux/amd64,便于更快完成集成验证;正式 main 和 tag 构建多架构镜像。
3. 部署云端测试环境¶
在 GitHub Actions 手动运行 Deploy Telegram Panel,选择 dev 分支,镜像使用对应 dev-latest 或带 SHA 的不可变标签,并在 update_mode 中选择 auto、image 或 binary。工作流会:
- 在云端
/home/docker/Telegram-Panel拉取dev; - 备份
docker-data中的 SQLite 数据文件; - 拉取镜像并保留
docker-compose.warp.yml等 override; - 重建
telegram-panel容器; - 检查容器状态、最近日志、
/ui/dashboard和/api/panel/auth/me。
部署脚本会把选择的更新模式写入 /data/update-mode.txt,并比较镜像 /app/version.txt 与 /api/panel/auth/me 的实际运行版本;两者不一致时部署失败,避免工作流表面成功但容器仍运行旧的持久化程序。
入口脚本会比较镜像内的 version.txt 与持久化自更新目录 /data/app-current/version.txt:
- 镜像版本更高时,优先启动镜像版本,并将旧的持久化程序目录归档为
/data/app-obsolete-*; - 持久化自更新版本更高时,继续优先使用已确认启动成功的自更新版本;
- 该比较同时适用于新版确认标记和旧版
.telegram-panel-self-update标记,避免历史自更新目录永久遮住新镜像; - 镜像包含
version.txt但旧持久化包没有该文件时,将旧包视为未知旧版本并归档,使用镜像目录,避免 v1.31.37 及更早更新包永久遮住新镜像; - 镜像也没有
version.txt时保持旧兼容行为,仍按启动确认标记选择目录。
可通过 .env 的 TP_UPDATE_MODE 明确选择 auto、image 或 binary。该策略同时注入入口脚本和应用配置,避免 UI 显示的更新方式与容器实际启动目录不一致。
因此,升级 Docker 镜像后如果页面仍显示旧版本,应先查看容器日志中的版本选择记录和 /data/app-obsolete-*,确认是否存在旧自更新目录残留。
部署完成不等于验收完成。验收时还要实际操作本次改动涉及的页面、API、后台任务或代理链路,并记录:
dev提交 SHA 和实际镜像标签;- 容器状态、启动日志和关键错误日志检查结果;
- 页面/API 的成功结果及关键响应;
- 数据持久化、重启恢复和权限边界检查结果;
- 失败时使用的回滚镜像或上一个可用提交。
若改动涉及 WARP 或其他代理管理能力,还要验证协议、容器网络、端口、账号绑定和重启后的状态恢复;不能只以 HTTP 健康检查作为通过依据。
4. 合并到 main¶
只有以下条件全部满足时,才创建或合并 dev -> main 的 PR:
- 本地构建和测试通过;
- 文档门禁通过;
- Docker 镜像工作流成功;
- 云端部署成功;
- 本次功能验收有明确通过证据;
- 没有未处理的回滚、数据迁移或安全风险。
Docker PR 工作流必须覆盖会改变镜像内容或运行版本的路径;至少包括 frontend/**、
src/**、docker/** 和 Directory.Build.props。如果相关 PR 没有出现 Docker 检查,
应先修复路径门禁并等待构建通过,不得把“未触发”视为“已通过”。
main 合并后会构建 latest 和多架构镜像;若需要正式版本,再按现有 Release 工作流创建 tag。正式发布不得反向替代 dev 验收。
创建正式 tag 前,必须先把 Directory.Build.props 中的 Version、AssemblyVersion、
FileVersion 和 InformationalVersion 更新为目标版本。Docker tag 构建和 Release 工作流
都会校验 vX.Y.Z 与项目 Version 完全一致;不一致时应停止发布,禁止生成“文件名是新
版本、包内二进制仍显示旧版本”的资产。成功判据是 Release ZIP 内 version.txt、运行时
/api/panel/auth/me 和 tag 三者一致。回滚时删除尚未发布的错误 tag;已经公开的错误版本
不得覆盖重发,应递增补丁版本重新发布。
Release 正文由 .github/workflows/release.yml 的 Generate Chinese release notes 步骤生成,不再直接使用 GitHub 默认的英文 What's Changed。生成规则:
- 正文顶部固定为
## 本次版本主要更新;变更列表在部署说明之前; - 如果 release/squash 提交正文中包含
## 本次版本主要更新小节,工作流会优先提取该小节内容,直到下一个二级标题为止,并为### 新增功能、### 修复问题、### 文档更新等已知分类标题补齐 emoji; - 如果提交正文没有该小节,工作流才回退到 commit 标题分类生成;
- conventional commit 类型会映射到带 emoji 的中文分类,如
feat→✨ 新增功能、fix→🐛 修复问题、release→🚀 版本发布; - 回退生成的列表项会去掉
fix:、feat:等英文前缀,只保留中文或可读标题与短 SHA; - 底部保留 GitHub compare 链接,标题为
🔗 完整变更记录。
发布 PR 的 squash 正文必须包含面向用户的 ## 本次版本主要更新 小节,示例:
## 本次版本主要更新
### ✨ 新增功能
- 账号导入时可以直接选择分类。
- 新增存储桶在线备份配置和立即备份入口。
## 验证
- Docker Build & Publish 通过。
- 云端部署验收通过。
提交信息仍建议写中文摘要,例如 fix: 修复导入分类选择不生效。如果提交标题是英文,工作流只能去掉类型前缀,不能可靠翻译业务含义;发布前应在 PR squash 标题或提交标题中改成中文。
5. 清理分支¶
合并确认后执行清理:
git fetch --prune origin
git branch --merged dev
git branch --merged main
git push origin --delete <已合并的功能分支>
git branch -d <已合并的功能分支>
删除前逐个检查 worktree 和未推送提交。main、dev、当前正在使用的分支和包含唯一未合并提交的分支不得删除。临时 worktree 只能在确认没有用户改动后移除。
发布证据模板¶
功能:
文档:
dev 提交:
镜像:
部署工作流:
容器状态:
健康检查:
功能验收:
回滚点:
main 合并:
分支清理: