跳到主要内容

发行自动化

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

脚本会自动:

  1. 检查工作树是否干净,以及下一个本地标签是否可用。
  2. 收集提交、文件、依赖、区域设置和未发行变更日志证据。
  3. 根据这些证据生成发行说明。
  4. 更新 package.json、工作区软件包文件、package-lock.json、Helm chart 和应用版本,以及 CHANGELOG.md
  5. 运行 npm run release:check,其中包括格式化、lint、构建、测试、安全审计和 npm 发布试运行。
  6. 只有所有检查都通过后,才提交发行变更并创建带注释的版本标签。

生成变更日志

预览下一段变更日志,不修改文件:

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_TOKENGITHUB_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/。