☰
Picard 发布流程实战指南:从版本同步、Git 标签到发布回滚的完整操作手册
2026/10/13 9:16:22 网站建设 项目流程
  • 桌面应用
  • 音频处理

【免费下载链接】picard

Picard is a cross-platform music tagger powered by the MusicBrainz database

项目地址:https://gitcode.com/gh_mirrors/pi/picard
点击查看免费下载

本文是 MusicBrainz Picard(跨平台音乐标签工具,由 MusicBrainz 数据库驱动)维护者的发布操作手册。它以仓库根目录下的 RELEASING.md 为核心骨架,完整覆盖正式版本发布前的翻译同步、仓库清理、常量重生成、NEWS 撰写、版本号升级、签名标签、推送与回滚的全过程,并结合 setup.py、picard/version.py 等源码说明每条命令背后的实现原理。读完本文,你可以独立执行一次从 master 分支出发的稳定版本发布,并在发布失败时安全回退。

一、发布流程总览与前置约定

Picard 的发布过程完全围绕 Git 仓库展开:所有状态变更(翻译 pot 文件、常量文件、NEWS.md、版本号)都以 commit 形式落地,最终以release-#.#.#格式的签名标签作为发布锚点。整体流程可划分为四个阶段:

  1. 发布准备期(正式发布前数周/数天):同步翻译模板、确认工作树干净。
  2. 发布执行期:重生成常量、撰写 NEWS、升级版本号、运行测试、创建签名标签。
  3. 开发版本回切:将版本号升为下一个 dev 版本并提交。
  4. 推送与应急回滚:推送 master 与标签,必要时执行回滚命令恢复发布前状态。

文档中的命令大量使用两个 shell 变量:$PICARD_REMOTE(远程仓库名,如origin)和$PICARD_VERSION/$PICARD_RELEASE_TAG。其中$PICARD_RELEASE_TAG即release-$PICARD_VERSION,仓库中的 scripts/tools/tag-release.sh 正是这一约定的自动化实现:它通过python -c "import picard; print(picard.__version__)"读取当前版本,然后执行git tag --sign "$TAG" --message="Release $PICARD_VERSION"。

二、发布准备期:同步翻译模板与仓库清理

2.1 同步 po/picard.pot 与源码

Picard 的界面字符串使用 gettext 管理。主模板po/picard.pot需要从源码中重新提取,以保证 Weblate 上翻译者看到的是最新字符串:

python setup.py regen_pot_file && git diff --quiet || git commit -m 'Update pot file' -- po/picard.pot

这条命令的语义是:先重新生成模板,如果git diff检测到po/picard.pot发生变化(git diff --quiet返回非零),则提交该文件;若没有变化则不做任何事。提取完成后推送到主远程仓库。关于翻译的完整说明见 po/README.md。

从源码实现看,regen_pot_file是 setup.py 中基于 Babelextract_messages自定义的命令类picard_regen_pot_file:它固定输出到po/picard.pot,输入目录为picard,并刻意忽略const目录(ignore_dirs = ('const',))。这是因为picard/const/下的常量字符串(如标签名与描述)属于独立翻译域,需要单独提取:

python setup.py regen_constants_pot_file

后者对应picard_regen_constants_pot_file命令,输出po/constants/constants.pot。如果环境中没有安装 Babel,这些命令会直接报错退出并提示"Babel is required to use this command (see po/README.md)",因此发布机必须预装 Babel。此外 AppStream 元数据与 XDG desktop 文件使用python setup.py regen_appdata_pot_file提取(见 setup.py 的picard_regen_appdata_pot_file类,内部调用xgettext --language=appdata与--language=desktop,再以msgmerge更新po/appstream/*.po)。

2.2 确保 Git 仓库工作树干净

发布必须从一个干净、与远程完全一致的 master 分支出发,避免带入未合入的本地改动。以下命令在本地仓库逐条执行:

# 1) 拉取远程并切到 master git fetch $PICARD_REMOTE && git checkout master # 2) 硬重置到远程 master,并清理未跟踪文件 git reset --hard $PICARD_REMOTE/master && git clean -f -d # 3) 移除旧的编译模块,防止过期 .pyc 干扰 find . -type f -name '*.pyc' -exec rm -f {} \; # 4) 打一个临时标签保存当前状态,发布失败时可回退到这里 git tag "before-release-$PICARD_VERSION" --force # 5) 移除文件中可能残留的 BOM 字节(正常情况下不应需要,发布前检查更稳妥) git ls-tree --full-tree -r HEAD --name-only |while read f; do sed -i '1s/^\xEF\xBB\xBF//' "$f"; done && git diff --quiet || git commit -a -m 'Remove nasty BOM bytes'

第 5 条命令遍历版本库中所有被跟踪文件,删除首行开头的 UTF-8 BOM(\xEF\xBB\xBF),若确有改动则统一提交为Remove nasty BOM bytes。这一步是防御性的:BOM 字节可能导致 Python 源码解析或 gettext 提取出现问题,发布前检查一次成本极低。

三、同步生成的常量文件

Picard 的两个常量模块picard/const/attributes.py(MB_ATTRIBUTES)与picard/const/countries.py(RELEASE_COUNTRIES)并非手写维护,而是由翻译 pot 文件生成:

python setup.py update_constants && git diff --quiet || git commit -a -m 'Update constants' -- picard/const/*.py

从 setup.py 的picard_update_constants命令类可以看到完整逻辑:默认情况下它会先调用scripts/tools/pull-shared-translations.py从 Weblate 拉取最新的 attributes/countries 共享翻译(该脚本面向https://translations.metabrainz.org/api/的musicbrainz项目,仅拉取翻译完成度不低于 10% 的语言),然后解析po/countries/countries.pot中带iso.code:注释的消息生成RELEASE_COUNTRIES字典,解析po/attributes/attributes.pot中来自DB:cover_art_archive.art_type/name、DB:medium_format/name、DB:release_group_primary_type/name、DB:release_group_secondary_type/name、DB:release_status/name五类位置的字符串生成MB_ATTRIBUTES字典。最终通过 scripts/package/constants.py.in 模板写出两个.py文件,文件头明确写着"Automatically generated - don't edit"。

若发布机不便访问 Weblate,可跳过拉取步骤、仅依据仓库内已有的 pot 文件重生成:

python setup.py update_constants --skip-pull

四、更新 NEWS.md

发布版本必须记录变更日志:

  1. 打开 NEWS.md,在文件顶部为即将发布的版本新增一节。
  2. 标题格式为## Version X.Y.Z - YYYY-MM-DD(例如仓库当前顶部即为## Version 3.0.1 - 2026-10-08)。
  3. 变更按### Bugfixes、### New Features、### Improvements三类分列。
  4. 每条变更应附带对应的 JIRA 工单链接,格式如- [PICARD-123](https://tickets.metabrainz.org/browse/PICARD-123) - Description of the change。
  5. 确保自上个版本以来的所有变更均已收录。

NEWS.md 的格式不只是给人看的,它同时是构建系统的数据源:setup.py 中的picard_build_appdata命令会以正则^## Version (?P<version>\d+(?:\.\d+){1,2}) - (?P<date>\d{4}-\d{2}-\d{2})解析 NEWS.md,为 AppStream 元数据生成<release date="..." version="..."/>列表。这意味着若标题格式写错,生成的org.musicbrainz.Picard.appdata.xml发布列表就会为空——这也是 NEWS 中曾出现"Generated Appstream appdata file has empty release list"类缺陷的根源。发布期间可借助仓库工具快速核对变更内容:

python scripts/tools/changelog-for-version.py 3.0.1 # 从 NEWS.md 提取指定版本章节 python scripts/tools/authors-between-releases.py # 列出两个标签间的代码贡献者与翻译者

五、升级 Picard 版本号并运行测试

5.1 版本号的存放位置与结构

版本号定义在 picard/init.py 顶部,当前为:

PICARD_VERSION = Version(3, 0, 1, 'final', 0)

Version是 picard/version.py 中定义的 namedtuple,五个字段为major, minor, patch, identifier, revision。其中identifier只能是dev、alpha、beta、rc、final之一(a/b是alpha/beta的别名,构造时会被归一化)。short_str()输出 PEP 440 规范字符串:final且 patch 为 0 时输出X.Y,否则输出X.Y.Z;预发布版本输出如3.0.0a4、3.0.0rc2、3.0.0.dev1等形式。版本比较通过sortkey属性完成,其排序键为(major, minor, patch, 标识符权重, revision),权重顺序为dev(0) < alpha(1) < beta(2) < rc(3) < final(4),这保证3.0.0dev<3.0.0rc<3.0.0final的语义正确。相关行为均有 test/test_versions.py 覆盖,例如test_version_conversion_short断言所有short_str()输出都符合 PEP 440 正则,test_lt断言dev版本小于alpha版本。

5.2 发布版与开发版的两次修改

第一步:设置为发布版本。编辑picard/__init__.py,写入新的发布版本元组,然后运行完整测试:

pytest

测试通过后提交本次版本号变更。

第二步(发布标签创建之后):切回开发版本。编辑picard/__init__.py,将版本号升级为下一个开发版本(例如发布3.0.1后设为3, 0, 2, 'dev', 0之类),再次运行:

pytest

提交变更。这样 master 分支始终指向"下一个开发版本",而发布版本只存在于标签上,避免日常开发被固定为已发布版本号。

提示:每日构建场景下还可以使用python setup.py patch_version(对应picard_patch_version命令),它会用当前时间 UTC 戳改写picard/__init__.py中的PICARD_BUILD_VERSION_STR(形如win32.20140415091256),运行时__version__会自动追加+<build>后缀;而 scripts/tools/patch-version.sh 则是按"最近发布标签以来的提交数-短哈希"(N-abc1234)来打补丁版本,供开发构建使用。

六、创建签名发布标签

git tag -s "$PICARD_RELEASE_TAG" -m "Release $PICARD_VERSION"

稳定版标签命名规范:release-#.#.#,例如release-2.1.0、release-3.0.1。注意:

  • 使用-s进行 GPG 签名,保证标签可被验证、不可被篡改;
  • 标签信息(-m)写明发布版本号;
  • 这一步骤应在"发布版本号提交"之后、切换回 dev 版本之前执行,因为标签要精确指向发布版本的提交。

七、推送新提交与标签到远程

git push "$PICARD_REMOTE" master:master git push "$PICARD_REMOTE" tag "$PICARD_RELEASE_TAG"

第一条推送 master 分支(包含 pot/常量/NEWS/版本号等全部发布提交),第二条推送签名标签。推送完成后,正式发布即告完成,后续的安装包构建、签名与分发由 CI/打包脚本(见 scripts/package 目录下的 Windows、macOS 打包脚本)继续处理。

7.1 发布后回滚(push 之后)

如果推送后发现问题需要撤回,RELEASING.md 提供了完整的回滚命令序列:

git tag -d "release-$PICARD_VERSION" # 删除本地发布标签 git reset --hard "before-release-$PICARD_VERSION" # 硬重置到发布前临时标签 git push "$PICARD_REMOTE" :"$TAG" # 删除远程标签 git push "$PICARD_REMOTE" "before-release-$PICARD_VERSION":master --force # 强制将远程 master 推回发布前状态

该流程依赖发布准备期创建的before-release-$PICARD_VERSION临时标签——这正是"发布前先打状态保存标签"这一步骤的意义所在。回滚属于强制推送操作,应仅在确认需要放弃本次发布时使用,并知会其他维护者。

八、发布检查清单与关键文件速查

将上述流程收敛为一张可逐项勾选的清单:

阶段操作验证方式
准备期python setup.py regen_pot_file并提交po/picard.potgit diff --quiet确认无残留
准备期fetch/reset/clean,移除*.pyc,处理 BOMgit status干净
准备期git tag "before-release-$PICARD_VERSION" --forcegit tag -l可见临时标签
常量python setup.py update_constants并提交picard/const/*.py检查picard/const/countries.py、attributes.py生成时间戳
变更日志按## Version X.Y.Z - YYYY-MM-DD格式更新 NEWS.md用 scripts/tools/changelog-for-version.py 验证可提取
版本号编辑 picard/init.py 为发布版本pytest全量通过
标签git tag -s "release-$PICARD_VERSION"git tag -v验证签名
回切版本号改为下一个 dev 版本pytest全量通过
推送push master + push tag远程git ls-remote确认
回滚(可选)删除标签、reset 到 before-release 标签、强制推送远程恢复发布前状态

涉及的核心文件与脚本:

  • 发布流程文档:RELEASING.md
  • 版本号定义:picard/init.py、版本模型 picard/version.py
  • 发布相关自定义命令:setup.py(regen_pot_file、regen_constants_pot_file、update_constants、patch_version、build_appdata等)
  • 辅助脚本:scripts/tools/README.md 下的 tag-release.sh、patch-version.sh、changelog-for-version.py、authors-between-releases.py
  • 翻译工作流:po/README.md
  • 版本模型测试:test/test_versions.py

九、常见问题与注意事项

  • Babel 缺失导致 regen 失败:regen_pot_file依赖 Babel,未安装时命令直接退出。发布前请按 po/README.md 的要求在发布环境安装 Babel 与 gettext 工具链。
  • NEWS 标题格式不可随意改动:picard_build_appdata依赖## Version X.Y.Z - YYYY-MM-DD精确格式生成 AppStream release 列表,格式偏差会导致发布列表为空。
  • update_constants需要 Weblate 访问权限:不带参数时默认先拉取共享翻译,需要 Weblate API key(可在仓库根目录放置.weblate.ini或使用--weblate-key);离线环境请使用--skip-pull。
  • 不要手工编辑生成文件:picard/const/*.py与po/picard.pot都是生成物,手工修改会在下次 re-gen 时被覆盖。
  • 发布版本必须是 final:picard/version.py校验identifier合法性,正式发布标签对应的版本应使用'final'标识,预发布(alpha/beta/rc)流程相同但版本标识符不同,标签命名建议沿用release-X.Y.Z前缀以便patch-version.sh等脚本用git describe --match "release-*"识别。

以上流程即为 Picard 从"代码就绪"到"版本发布上架"的完整工程链路。维护者只需严格按照 RELEASING.md 的顺序执行,即可保证每次发布的可复现性、可验证性与可回滚性。

  • 桌面应用
  • 音频处理

【免费下载链接】picard

Picard is a cross-platform music tagger powered by the MusicBrainz database

项目地址:https://gitcode.com/gh_mirrors/pi/picard
点击查看免费下载

相关推荐

上一篇:react-admin 的 `<DateTimeInput>` 组件:日期时间输入、格式转换与时区处理完整指南
下一篇:在 Ray Tune 中使用 Nevergrad:无导数超参数优化的完整实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询