Dangerzone 发布前准备完全指南:pre-release 任务清单、版本号多点同步与 Linux 平台维护
【免费下载链接】dangerzoneTake potentially dangerous PDFs, office documents, or images and convert them to safe PDFs项目地址: https://gitcode.com/GitHub_Trending/da/dangerzone
Dangerzone 的发布流程分为六个阶段,其中“Pre-release(发布前准备)”是全部工作的起点:它要求发布管理者在构建任何发行物之前,就完成问题跟踪创建、依赖锁文件刷新、多处版本号同步、Linux 平台清单维护、Debian changelog 更新、发布说明草稿和 rc1 标签等一系列前置任务。本文基于仓库中 发布前准备文档 完整展开这份任务清单,并结合 generate-release-tasks.py、dev_scripts/qa.py 等源码说明每个步骤背后的实际机制,帮助你理解“为什么必须改这些文件、改哪里、如何验证”。
一、Pre-release 在整体发布流程中的位置
Dangerzone 需要同时面向 Debian、Ubuntu、Fedora、Qubes OS、macOS、Windows 多个发行渠道出包,因此其发布被拆分为六个阶段(见 发布流程总览):
- Pre-release(发布前准备,即本文主题)
- Prepare build environments(准备构建环境)
- Sign and release container image(签名并发布容器镜像)
- Build release artifacts(构建发行物)
- QA
- Release
Pre-release 阶段的特殊性在于:它完全可以在开发者自己的笔记本上执行,不依赖任何构建环境。原文档明确说明“Here is a list of tasks that should be done before issuing the release. They can run from the developer's laptop and are not tied to any build environment.”这一点很关键——所有任务都是修改仓库内容(版本号、文档、changelog、依赖锁),而非触发 CI。
1.1 用一个 issue 跟踪整体进度
任务清单的第一步是创建一个名为QA and Release for version<VERSION>的 GitHub issue,用来跟踪整个发布周期的进度。issue 的正文内容可以自动生成:
poetry run ./dev_scripts/generate-release-tasks.py从源码结构看,generate-release-tasks.py 的实现很精巧。它维护了一个文档列表:
RELEASE_DOCS_DIR = pathlib.Path("docs") / "developer" / "release" DOCS = [ "pre-release.md", "prepare-build-envs.md", "build.md", "qa.md", "release.md", ]然后对每份文档执行extract_checkboxes():两轮扫描,第一轮收集所有以#开头的标题行和所有- [ ]复选框行;第二轮按 Markdown 标题层级裁剪,只保留“当前标题层级及更浅层级”的内容(这样生成的 issue 正文就是各阶段文档的目录级概览,而不是每个子节都铺开的细节)。由于它是按git rev-parse --show-toplevel定位仓库根目录后直接读取这五个 Markdown 文件的,这意味着 release 文档本身就是 issue 内容的单一事实来源——后续修改文档中的复选框,issue 模板会自动跟随变化。
注意:脚本中列出的
prepare-build-envs.md与build.md对应当前仓库docs/developer/release/目录下的同名文件,说明该目录是整份发布文档集的组织中心。
二、依赖锁文件刷新:两条并行的锁链
Dangerzone 有两条互相独立的依赖链,发布前都要刷新:
| 命令 | 管理对象 | 锁文件 |
|---|---|---|
poetry lock --regenerate | Python 依赖(由 pyproject.toml 声明) | poetry.lock |
poetry run mazette lock | 构建/发布所需的二进制资产(asset 依赖) | mazette.lock |
前一条是标准的 Poetry 流程:重新解析依赖并生成新的poetry.lock,确保新发布携带当时最新兼容版本的 Python 包。
后一条由 mazette(仓库根目录下的mazette.lock即其产物)管理。从 dev_scripts/env.py 与 dev_scripts/qa.py 的用法看,poetry run mazette install是开发者本地下载运行所需资源(二进制、字体等 assets)的标准入口,而poetry run mazette lock则在发布时刷新这些资产的固定引用——这与 dev_scripts/qa.py 中 QA 清单反复出现的 “Download the necessary assets usingpoetry run mazette install” 形成上下游呼应:QA 环境安装的是 lock 文件里固定的资产版本,因此发布前刷新 lock 能提前暴露资产引用问题。
此外清单中还有一项外部工具检查:查看 WiX(Windows 安装包工具)是否有新 release,如有需要则升级。原文档同时引用了一个 issue 作为历史背景,说明 WiX 版本曾与 Windows 构建产物兼容性相关——这一步属于“工具链升级”性质,是否执行取决于当前 WiX 版本的稳定性。
三、版本号的多点同步:四个必须一致的位置
这是 pre-release 中最容易出错的部分。仓库中版本号分散在四处,必须全部更新到同一个值(当前仓库快照中的实际值为0.11.0,可作为参照格式):
| 位置 | 说明 | 当前仓库中的实际值 |
|---|---|---|
| pyproject.toml | Poetry 项目元数据第 3 行的version = "0.11.0" | version = "0.11.0" |
| share/version.txt | 单行纯文本版本文件,运行时/构建脚本读取 | 0.11.0 |
| install/linux/dangerzone.spec | RPM spec 文件第 37 行 | Version: 0.11.0 |
| debian/changelog | 需要新增一条changelog 条目而非改旧条目 | 首条为dangerzone (0.11.0) unstable; urgency=low |
关于share/version.txt的读取方,源码中有直接证据:dev_scripts/env.py 中的dz_version()函数就是从该文件读取版本号:
def dz_version(): """Get the current Dangerzone version.""" with open(git_root() / "share/version.txt") as f: return f.read().strip()该函数随后被用于拼装本地包的匹配模式(如{pkg_name}-{version}-*.fc{...}.rpm),也就是说share/version.txt一旦与pyproject.toml不一致,开发环境的包安装/测试脚本就会找不到对应产物。这解释了为什么原文档把这两个文件的更新列为并列的必做项。
3.1 Debian changelog 条目
“Bump the Debian version”的正确做法是在 debian/changelog顶部追加一条新记录,格式参照既有条目:
dangerzone (0.11.0) unstable; urgency=low * Released Dangerzone 0.11.0 -- Freedom of the Press Foundation <info@freedom.press> Tue, 9 Jun 2026 15:25:20 +0300每条包含版本头(dangerzone (X.Y.Z) unstable; urgency=low)、变更摘要行(* Released Dangerzone X.Y.Z)以及维护者签名行(维护者、邮箱、日期)。新发布只需把版本号替换为本次版本并更新日期即可。
3.2 (可选)容器镜像 API 版本:v1 → v2
清单中还有一项可选项:“Bump image version fromv1tov2, if the API has changed.”这里的 “image version” 指的是容器镜像仓库路径中的大版本段,而非应用版本号。当前仓库 share/image-name.txt 的内容是:
ghcr.io/freedomofpress/dangerzone/v1dev_scripts/qa.py 的 QA 场景中同样以ghcr.io/freedomofpress/dangerzone/v1作为镜像标识进行升级验证(“Dangerzone successfully installs the container image”场景)。可以推断:v1表示镜像格式/API 的第一代;只有当镜像对外 API 发生不兼容变化时,才需要切到v2并让各处引用跟随。若无 API 变更,此项直接跳过——这与“宁可发布无聊而稳定的版本”(README 原话 “either boring uneventful releases or gung-ho brittle ones. Pick your poison (the first one)”)的发布哲学一致。
四、文档与发布材料更新
版本号同步完成后,还有四项文档/材料类任务:
更新 INSTALL.md 中的下载链接,使其指向新版本。当前仓库中这些链接形如
https://github.com/freedomofpress/dangerzone/releases/download/v0.11.0/Dangerzone-0.11.0-arm64.dmg(macOS Apple Silicon)、.../Dangerzone-0.11.0-i686.dmg(macOS Intel)、.../Dangerzone-0.11.0.msi(Windows)。注意原文档的提示:具体下载链接要等发布完成、资产上传后才能回填,因此这一步在 pre-release 阶段先定位到需要替换的位置,发布阶段再落实。如有必要更新 README.md 中的应用截图(界面发生重大变化时)。
更新 CHANGELOG.md,列出自上一版本以来所有重大变更。该文件采用 Keep a Changelog 格式并遵循语义化版本,顶部维护一个
[Unreleased]段;发布时把 Unreleased 内容固化为新版本段。创建 draft release 草稿。发布说明文本从 docs/templates 目录的模板复制而来,当前仓库包含两个模板:
- release-notes-regular.md(常规发布)
- release-notes-security.md(安全发布)
常规模板的骨架是:一句总述(新特性/稳定性改进/安全修复)、亮点列表(重大成果、新平台支持、社区贡献致谢),末尾附指向 CHANGELOG.md 对应版本锚点的链接,模板中的
<RELEASE_TAG>、<RELEASE_ANCHOR>占位符需替换为实际标签与锚点。将发布说明送编辑(editorial)审校——这是流程性任务,确保对外措辞准确。
五、Linux 平台清单维护:新增与移除
这是 pre-release 中最需要外部信息输入的环节。当前支持的 Linux 发行版是Debian、Ubuntu 和 Fedora(Qubes OS 在发布层面被视为 Fedora 的特例)。每个发布周期都要回答两个问题:是否有新版本加入了?是否有现有版本 EOL(停止支持)了?原文档建议用 endoflife.date 这类工具查询各发行版的生命周期状态。
5.1 新增一个平台版本(beta / RC / 正式版均可)
原文档给出了五步流程,下面结合源码展开每一步“具体要改哪”:
步骤 1:加入 CI 工作流,让该版本进入自动化测试。文档列出需要查看的位置是.circleci/config.yml与.github/workflows/ci.yml,以及 dev_scripts/env.py 和 dev_scripts/qa.py。需要说明的是,在当前仓库快照中,CI 主工作流是 .github/workflows/ci.yml(.circleci/config.yml未包含在本快照中,文档中的该条目反映的是历史/并行配置)。真正的“平台注册表”有两处,都必须动:
dev_scripts/env.py:基础发行版由
DISTROS = ["debian", "fedora", "ubuntu"]定义,容器运行时为podman/docker;更关键的是各发行版 Dockerfile 中对具体版本号的分支判断,例如 Ubuntu 22.04/jammy 需要额外注入apt-tools-prod.sources与 conmon 升级步骤(源于 dev_scripts/apt-tools-prod.pref 等配套文件),Ubuntu 24.04/26.04/25.10 等新版则需要DOCKERFILE_UBUNTU_REM_USER片段来移除 23.04 起镜像自带的ubuntu用户。新增版本时若存在此类版本特化行为,需要在这里登记。dev_scripts/qa.py:每个受测平台对应一个类,
DISTRO+VERSION两个类属性即平台 ID。当前快照中的平台注册表为:class QADebianBookworm(QADebianBased): DISTRO = "debian"; VERSION = "bookworm" class QADebianTrixie(QADebianBased): DISTRO = "debian"; VERSION = "trixie" class QADebianForky(QADebianBased): DISTRO = "debian"; VERSION = "forky" class QAUbuntu2204(QADebianBased): DISTRO = "ubuntu"; VERSION = "22.04" class QAUbuntu2404(QADebianBased): DISTRO = "ubuntu"; VERSION = "24.04" class QAUbuntu2604(QADebianBased): DISTRO = "ubuntu"; VERSION = "26.04" class QAUbuntu2510(QADebianBased): DISTRO = "ubuntu"; VERSION = "25.10" class QAFedora44(QAFedora): VERSION = "44" class QAFedora43(QAFedora): VERSION = "43"这些类通过
__init_subclass__自动注册进QABase.platforms字典,键为get_id()返回的"{DISTRO}-{VERSION}"(如ubuntu-24.04)。因此新增平台 = 仿照现有类新增一个子类即可,qa.py <platform>的 CLI 参数 choices 会自动包含它。
步骤 2:用dev_scripts/qa.py本地测试该版本。原文档特别强调“Focus on the GUI part, since the basic functionality is already tested by our CI workflows”——CI 已覆盖基础功能,本地测试聚焦 GUI。运行方式:
poetry run ./dev_scripts/qa.py {distro}-{version}例如poetry run ./dev_scripts/qa.py ubuntu-26.04。从 dev_scripts/qa.py 的QALinux.start()看,脚本会依次自动执行:构建开发环境镜像(调用env.py ... build-dev)、poetry run mazette install下载资产、make test跑测试套件、构建.deb/.rpm包、构建 QA 端用户环境(env.py ... build),最后交互式逐项询问 QA 场景是否通过。常用选项有--try-auto(自动尝试可自动化的步骤)、--skip-manual(跳过手动步骤)、--check-refs(只校验文档引用一致性后退出)。
还有一个值得了解的机制:qa.py内置了Reference类,把脚本中的CONTENT_QA、CONTENT_BUILD_*等缓存文本与 docs/developer/release/qa.md、BUILD.md 中的对应章节做一致性比对,不一致就打印 diff 并以非零码退出。换句话说,文档与自动化脚本之间有一道强制同步检查,修改文档里的操作步骤时必须同步更新qa.py中的缓存副本。
步骤 3:更新 INSTALL.md 并记一笔 CHANGELOG.md。新平台要进入安装文档的支持列表,同时在 changelog 中留痕,供用户知晓支持范围变化。
步骤 4:若该版本是新的 stable 发布,按需更新RELEASE.md与BUILD.md。当前仓库快照中对应内容以 BUILD.md 形式存在(构建/运行开发环境说明),qa.py的 Reference 检查也直接引用了它。
步骤 5:以上改动提 PR,走正常评审合并流程。
5.2 移除一个 EOL 版本
原文档给出两步:
- 从仓库中移除对该版本的一切提及。除检查新增平台涉及的那些文件(CI 配置、dev_scripts/env.py、dev_scripts/qa.py、INSTALL.md)外,用
grep全局搜索版本号/代号(如22.04、bookworm),逐一清理——包括env.py中版本特化的 Dockerfile 分支、qa.py中对应的平台子类。 - 在 CHANGELOG.md 中添加移除说明,让用户知道某发行版版本不再被测试/支持。
六、打 rc1 标签:发布前准备的收尾动作
清单最后一项:
git tag -s v<version>-rc1 # 例如 git tag -s v0.9.1-rc1对main分支的 tip 打一个带签名的-rc1候选标签。使用签名标签(-s而非-a/-m)保证候选版本可被 GPG 验证;-rc1后缀表明这是第一个 release candidate,后续构建阶段将基于该标签(而非移动的 HEAD)构建与签名各平台产物,从而保证“发布说明里声明的代码”与“用户实际下载的产物”严格对应。
七、任务清单速查表
把 pre-release.md 的完整清单整理为可执行顺序:
| # | 任务 | 涉及文件/命令 | 性质 |
|---|---|---|---|
| 1 | 创建 “QA and Release for version X” issue | poetry run ./dev_scripts/generate-release-tasks.py生成正文 | 必做 |
| 2 | 新增 Linux 平台 / 移除 EOL 平台 | dev_scripts/env.py、dev_scripts/qa.py、INSTALL.md、CHANGELOG.md | 必做(按需) |
| 3 | 刷新 Python 依赖锁 | poetry lock --regenerate→poetry.lock | 必做 |
| 4 | 刷新资产依赖锁 | poetry run mazette lock→mazette.lock | 必做 |
| 5 | 检查并升级 WiX(Windows 打包工具链) | 外部工具版本检查 | 按需 |
| 6 | 更新 pyproject.toml 的version | 第 3 行 | 必做 |
| 7 | 更新 share/version.txt | 单行文本 | 必做 |
| 8 | 更新 install/linux/dangerzone.spec 的Version: | 第 37 行 | 必做 |
| 9 | (可选)容器镜像 API 从v1升到v2 | share/image-name.txt 等引用处 | 仅 API 变更时 |
| 10 | Debian 版本 bump:新增 changelog 条目 | debian/changelog | 必做 |
| 11 | 更新 INSTALL.md 下载链接(发布后回填) | macOS/Windows 下载 URL | 必做 |
| 12 | 视情况更新 README.md 截图 | 截图资产 | 按需 |
| 13 | 更新 CHANGELOG.md 重大变更列表 | [Unreleased]段固化 | 必做 |
| 14 | 从 docs/templates 模板创建 draft release 说明 | release-notes-regular.md | 必做 |
| 15 | 发布说明送编辑审校 | 流程动作 | 必做 |
| 16 | 对maintip 打签名标签v<version>-rc1 | git tag -s v0.9.1-rc1 | 必做 |
八、小结:pre-release 的本质
回顾整个阶段,它的设计逻辑可以概括为三句话:
- 一切以仓库内文本为单一事实来源。issue 模板由 release 文档自动生成,QA 脚本内嵌文档章节并强制一致性检查,版本号在四个文件中多点同步——任何一处遗漏都会在后续构建/QA 阶段以“找不到包”“链接失效”“签名对不上”等形式爆发。
- 平台支持面是显式管理的资产。新增/移除 Linux 版本必须同时改 CI、
env.py、qa.py、文档四处并留 changelog 痕迹,而不是随新版本“顺带支持”。 - 候选标签锁定发布基线。
v<version>-rc1签名标签把“要发布的代码”从移动的main上摘出来,使后续签名、构建、QA、正式 release 各阶段都站在同一基线上。
完成上述清单后,仓库就进入了下一阶段——准备构建环境并签名容器镜像,发布工作从“改文档和版本号”转入“出产物和验证”。
【免费下载链接】dangerzoneTake potentially dangerous PDFs, office documents, or images and convert them to safe PDFs项目地址: https://gitcode.com/GitHub_Trending/da/dangerzone
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考