发行自动化
Libre WebUI 发行版通过仓库根目录下的发行脚本创建。脚本会读取上一个版本标签以来的真实 git 历史,更新软件包版本、写入变更日志、运行发行检查、提交发行变更并创建版本标签。GitHub 是构建和二进制发布源;发行元数据及具名产物链接会镜像到项目的 Forgejo 仓库。
一次性本地设置
安装依赖并启用仓库钩子:
npm install
npm run setup-hooks
钩子设置会配置:
.githooks/commit-msg:验证 Conventional Commit.githooks/pre-commit:格式检查.gitmessage:本地提交消息模板
创建发行版
在准备打标签的分支上,确保工作树干净,然后从仓库根目录运行发行脚本:
# Patch release
npm run release
# Minor release
npm run release:minor
# Major release
npm run release:major
脚本会自动:
- 检查工作树是否干净,以及下一个本地标签是否可用。
- 收集提交、文件、依赖、区域设置和未发行变更日志证据。
- 根据这些证据生成发行说明。
- 更新
package.json、工作区软件包文件、package-lock.json、Helm chart 和应用版本,以及CHANGELOG.md。 - 运行
npm run release:check,其中包括格式化、lint、构建、测试、安全审计和 npm 发布试运行。 - 只有所有检查都通过后,才提交发行变更并创建带注释的版本标签。
生成变更日志
预览下一段变更日志,不修改文件:
npm run changelog
根据生成的段落手动更新 CHANGELOG.md:
npm run changelog -- update
默认情况下,变更日志生成器可以请求本地 Ollama 兼容模型生成润色后的草稿,再根据收集到的 git 证据验证结果。如果 AI 不可用或输出看起来不安全,脚本会回退到确定性生成器。
常用覆盖项:
CHANGELOG_AI=0 npm run release:minor
CHANGELOG_AI_MODEL=glm-5.2:cloud npm run changelog
OLLAMA_BASE_URL=http://127.0.0.1:11434 npm run release
推送发行版
创建发行提交和带注释标签后,只发布脚本显示的确切分支提交与标签。先将生产分支推送到 Forgejo,再推送到 GitHub,并明确禁用附带标签:
git -c push.followTags=false push \
https://git.kroonen.ai/libre-webui/libre-webui.git \
HEAD:refs/heads/main
git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
refs/heads/main
git -c push.followTags=false push \
https://github.com/libre-webui/libre-webui.git \
HEAD:refs/heads/main
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
refs/heads/main
两个返回的分支 SHA 都必须等于预期的本地发行提交。发布标签前,等待针对该确切提交的必需 GitHub 工作流全部通过。
确认版本标签在两个服务上都尚不存在,然后先将这个标签推送到 Forgejo,再推送到 GitHub:
git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git -c push.followTags=false push \
https://git.kroonen.ai/libre-webui/libre-webui.git \
refs/tags/vX.Y.Z:refs/tags/vX.Y.Z
git -c push.followTags=false push \
https://github.com/libre-webui/libre-webui.git \
refs/tags/vX.Y.Z:refs/tags/vX.Y.Z
git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
将 vX.Y.Z 替换为发行标签。对于带注释标签,请同时验证标签对象 SHA 及其剥离后的提交 SHA。绝不要使用 git push --tags,它可能会发布无关的本地标签。
CI 发行路径
推送 v* 标签会运行 GitHub 发行工作流。该工作流会:
- 运行
npm run release:check - 为 macOS、Windows 和 Linux 构建 Electron 产物
- 从
CHANGELOG.md中对应的段落创建 GitHub Release - 将发行记录和具名产物链接镜像到 Forgejo
- 构建 Docker 镜像
- 使用与发行标签相同的版本发布 Helm chart
- 使用
NPM_TOKEN发布 npm 软件包
打标签前也可在本地运行相同检查:
npm run release:check
Forgejo 发行镜像
镜像使用存储为加密 GitHub Actions secret FORGEJO_TOKEN 的 Forgejo 个人访问令牌。只授予令牌 write:repository 范围,确保其所有者能写入 libre-webui/libre-webui,并且绝不要提交或打印该令牌。
镜像有意设计成幂等操作。它按标签查找发行版,只创建缺失的发行记录、协调其 GitHub 发行元数据,并跳过已存在的产物链接。因此,在网络或工作流故障后重试时,可以补齐缺失工作,而不会重复创建发行版或资产。
Forgejo 发行资产是指向相应公开 GitHub browser_download_url 的具名外部链接。GitHub 仍托管二进制文件,而 Forgejo 会显示相同的可下载文件名,无需重复存储数十 GB 的桌面端产物。源代码归档则由每项服务分别根据确切标签生成。
预览或回填单个发行版
检查将要发生的变化,但不写入 Forgejo:
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z --dry-run
从维护者的机密管理器将 FORGEJO_TOKEN 和 GITHUB_TOKEN 加载到进程环境后,镜像该发行版:
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z
确切标签必须已同时存在于 GitHub 和 Forgejo 上,并且解析到相同的标签对象和剥离后提交,才能镜像发行版。
预览或回填所有发行版
对照 Forgejo 审计每个 GitHub Release:
node scripts/mirror-forgejo-releases.mjs --all --dry-run
回填每个缺失或不完整的 Forgejo Release:
node scripts/mirror-forgejo-releases.mjs --all
--all(包括试运行)需要 GITHUB_TOKEN,因为确切标签一致性校验和资产发现所需的请求量超过 GitHub 匿名 API 限制。不使用 --dry-run 时还需要 FORGEJO_TOKEN。
--all 路径会对两个 API 进行分页,并考虑 GitHub Release 对象,而不是每个 Git 标签。有意不提供 GitHub Release 的标签在 Forgejo 上仍只会是标签。回填后再次运行试运行;它应报告没有待处理变更。
不可变标签策略
已发布的版本标签不可变。标签一旦存在于任一远程:
- 不要删除。
- 不要强制推送。
- 不要将其移动到修正后的提交。
- 不要为不同内容复用其语义版本。
若已发布的发行内容有误,请修正源代码和变更日志,并发布下一个补丁版本。若只是缺少发行页面或外部资产链接,请重新运行幂等镜像,不要改动标签。
在引入双重发行镜像期间,Forgejo v0.8.6 标签曾进行一次经明确批准的重新对齐。它修复了两个历史标签对象:二者描述相同的源代码树,但遵循不同的提交谱系。这次经审计的迁移不构成移动已发布标签的先例。
Helm 版本策略
Helm chart 的 version、chart appVersion、根软件包版本和发行标签有意使用同一个语义版本。发行脚本会一起推进这些版本,CI 会拒绝不一致的情况。
chart 只从不可变的 v* 发行标签发布。不要在现有 chart 版本下发布经过修改的 chart 内容。chart 变更必须进入下一应用发行版,从而获得新版本。
Chart 版本 0.14.1 带有一次性摘要覆盖,因为该发行版早于语义 Docker 标签。该摘要标识经过验证的多架构 0.14.1 镜像。发行脚本创建下一发行版时会清除此覆盖,此后默认镜像解析为 chart appVersion。
Docker 工作流会从同一个 v* 发行标签向 GHCR 和 Docker Hub 发布该语义版本标签。Helm 发布最多等待 20 分钟,直到匹配的公开 Docker Hub 镜像可用;若默认镜像缺失,则会失败而不发布 chart。捆绑的 Ollama 镜像仍可独立配置,默认使用其上游 latest 标签。
Conventional Commits
提交消息应采用 Conventional Commit 格式:
<type>[optional scope]: <description>
常见类型:
feat:面向用户的功能fix:缺陷修复docs:文档更新refactor:内部代码重构perf:性能改进test:测试覆盖chore:维护、发行或构建工作
破坏性变更使用 !:
git commit -m "feat!: remove deprecated endpoint"
git commit -m "fix(auth)!: change token validation"
故障排查
工作目录不干净
发行前提交或暂存本地变更:
git status --short
git add .
git commit -m "fix: resolve pending changes"
没有可发行的变更
检查上一个标签以来的提交:
git log $(git describe --tags --abbrev=0)..HEAD --oneline
变更日志需要手动编辑
编辑 CHANGELOG.md,然后在发布标签前提交修正:
git add CHANGELOG.md
git commit -m "docs: refine changelog"
回滚本地发行提交
如果发行提交和标签均未推送:
git tag -d v0.12.0
git reset --soft HEAD~1
如果任一远程已存在该标签,请勿删除或替换它。请在 main 上修复问题,创建下一个补丁发行版,并通过完整门禁发布这个新的不可变标签。
Forgejo 镜像不完整
先验证两个远程的标签对象 SHA 和剥离后提交 SHA 是否匹配。然后预览并重试受影响的发行版:
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z --dry-run
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z
授权失败意味着 FORGEJO_TOKEN 缺失、已过期、属于无仓库访问权限的用户,或缺少 write:repository。远程标签缺失或不同必须另行调查;发行镜像绝不会创建或移动 Git 标签。
维护者文件
.gitmessage- 提交消息模板.githooks/commit-msg- Conventional Commit 验证.githooks/pre-commit- 格式预检scripts/release.js- 发行编排scripts/mirror-forgejo-releases.mjs- 幂等 Forgejo 发行镜像与回填scripts/generate-changelog.js- 变更日志预览/更新命令scripts/lib/releaseNotes.js- 证据收集和变更日志生成.github/workflows/release.yml- 标签驱动的 CI 发行工作流.github/workflows/helm-publish.yml- Helm 验证和标签发布
有关 Conventional Commits 的更多信息,请访问 https://www.conventionalcommits.org/。