- 桌面应用
- 音频处理
【免费下载链接】picard
Picard is a cross-platform music tagger powered by the MusicBrainz database
本文是 MusicBrainz Picard(跨平台音乐标签工具,由 MusicBrainz 数据库驱动)维护者的发布操作手册。它以仓库根目录下的 RELEASING.md 为核心骨架,完整覆盖正式版本发布前的翻译同步、仓库清理、常量重生成、NEWS 撰写、版本号升级、签名标签、推送与回滚的全过程,并结合 setup.py、picard/version.py 等源码说明每条命令背后的实现原理。读完本文,你可以独立执行一次从 master 分支出发的稳定版本发布,并在发布失败时安全回退。
一、发布流程总览与前置约定
Picard 的发布过程完全围绕 Git 仓库展开:所有状态变更(翻译 pot 文件、常量文件、NEWS.md、版本号)都以 commit 形式落地,最终以release-#.#.#格式的签名标签作为发布锚点。整体流程可划分为四个阶段:
- 发布准备期(正式发布前数周/数天):同步翻译模板、确认工作树干净。
- 发布执行期:重生成常量、撰写 NEWS、升级版本号、运行测试、创建签名标签。
- 开发版本回切:将版本号升为下一个 dev 版本并提交。
- 推送与应急回滚:推送 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
发布版本必须记录变更日志:
- 打开 NEWS.md,在文件顶部为即将发布的版本新增一节。
- 标题格式为
## Version X.Y.Z - YYYY-MM-DD(例如仓库当前顶部即为## Version 3.0.1 - 2026-10-08)。 - 变更按
### Bugfixes、### New Features、### Improvements三类分列。 - 每条变更应附带对应的 JIRA 工单链接,格式如
- [PICARD-123](https://tickets.metabrainz.org/browse/PICARD-123) - Description of the change。 - 确保自上个版本以来的所有变更均已收录。
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.pot | git diff --quiet确认无残留 |
| 准备期 | fetch/reset/clean,移除*.pyc,处理 BOM | git status干净 |
| 准备期 | git tag "before-release-$PICARD_VERSION" --force | git 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
相关推荐
IPython 发布流程完全指南:从发布说明、Git 标签到 PyPI 上传的 10 步操作手册
IPython 发布流程完全指南:从发布说明、Git 标签到 PyPI 上传的 10 步操作手册 本文以仓库内 docs/source/contributing
开发工具KindEditor自定义工具栏配置:打造符合业务需求的编辑界面
KindEditor自定义工具栏配置:打造符合业务需求的编辑界面 KindEditor是一款功能强大的富文本编辑器,通过灵活的工具栏配置,你可以轻松打造符合自身
前端UI组件cryptography 项目发布流程实战指南:从版本号提升、签名 Tag 到 PyPI 发布的完整操作手册
cryptography 项目发布流程实战指南:从版本号提升、签名 Tag 到 PyPI 发布的完整操作手册 导读 本文以 cryptography 项目官方发
密码学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考