news 2026/9/17 21:52:53

Dangerzone 发布流程实战:从 PGP 签名标签、资产签名到 GitHub 草稿发布的最后一哩路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Dangerzone 发布流程实战:从 PGP 签名标签、资产签名到 GitHub 草稿发布的最后一哩路

Dangerzone 发布流程实战:从 PGP 签名标签、资产签名到 GitHub 草稿发布的最后一哩路

【免费下载链接】dangerzoneTake potentially dangerous PDFs, office documents, or images and convert them to safe PDFs项目地址: https://gitcode.com/GitHub_Trending/da/dangerzone

本文以 Dangerzone 仓库的发布文档 release.md 为主体,完整拆解一次正式发布的最终阶段:如何创建 PGP 签名的 git tag、打包源码归档、用 grype 扫描容器镜像、通过 dev_scripts/sign-assets.py 计算哈希并签名全部资产、再经 dev_scripts/upload-asset.py 上传至 GitHub 草稿发布,直至正式发布。读完后你可以完整复现 Dangerzone 发布经理在"发布日"执行的每一条命令,并理解每个自动化脚本在底层做了什么、为什么这样做。

一、release.md 在整体发布流程中的位置

Dangerzone 的一次新版本发布横跨多个支持平台(macOS、Windows、Debian/Ubuntu/Fedora Linux、Qubes OS),流程复杂。docs/developer/release/README.md 把整个流程拆成六个阶段:

  1. Pre-release
  2. Prepare build environments(构建环境准备)
  3. Sign and release container image(容器镜像构建与签名,在独立的dangerzone-image仓库中完成)
  4. Build release artifacts(构建发布产物)
  5. QA
  6. Release ← 本文主角

也就是说,release.md描述的是最后一步:前五个阶段完成后,发布负责人已经拥有了一份通过 QA 验证的完整资产集合(安装包、源码包、签名后的容器镜像),剩下的工作全部是"签名、打包、上传、宣布"。这也是为什么文档开篇只有一句话——"When confident that the release doesn't need any more changes"(当确信发布物不再需要任何修改)——就开始逐项执行。

执行本阶段前,可以先做一次版本一致性自检。以当前仓库为例,版本号0.11.0同时出现在以下四处,任何一处不一致都应在发布前修正(这正是 pre-release.md 中列出的任务):

  • share/version.txt:0.11.0
  • pyproject.toml:version = "0.11.0"
  • install/linux/dangerzone.spec:Version: 0.11.0
  • debian/changelog:dangerzone (0.11.0) unstable; urgency=low

Pre-release 阶段还会将main分支顶点打上一个 RC 标签(例如git tag -s v0.11.1-rc1),供构建环境构建产物和 QA 验证;等到 QA 通过、发布日到来,才会打上本文要讲的正式版本标签

二、步骤一:创建并推送 PGP 签名的 git tag

发布的第一项任务是为本版本创建一个PGP 签名的 git tag,例如针对v0.11.0

git tag -s v0.11.0 git push origin v0.11.0

-s参数让 git 使用 GPG 私钥对 tag 本身做签名(与 pre-release 阶段的-rc1标签采用同样的做法)。签名 tag 的意义在于:任何拉取该仓库的人都能用 Dangerzone 的公开发布公钥验证"这个版本号确实由官方发布经理标注",而不是来自被篡改的 fork。Dangerzone 的公开 PGP 公钥随仓库分发,见 share/freedomofpress-dangerzone.pub(附 share/freedomofpress-dangerzone.pub.asc 签名)。这个公钥后续还会被签名脚本用于对资产签名,形成贯穿 tag → 资产 → 校验和文件的完整信任链。

三、步骤二:用 git archive 打包源码归档

接下来从正式 tag 生成tar.gz源码归档:

export VERSION=$(cat share/version.txt) git archive --format=tar.gz -o dangerzone-${VERSION:?}.tar.gz --prefix=dangerzone/ v${VERSION:?}

这条命令有几个值得注意的细节:

  • 版本号取自 share/version.txt,而不是手写,避免 tag、归档文件名与仓库内容三者不一致;
  • ${VERSION:?}是 bash 的参数展开保护:若VERSION为空,shell 会直接报错退出,而不是静默地生成一个名为dangerzone-.tar.gz的垃圾文件;
  • --prefix=dangerzone/让解包后的顶层目录是dangerzone/,符合 FHS 和源码分发惯例;
  • git archive ... v${VERSION}只归档该 tag 指向的干净快照,不含未提交改动和 git 元数据,保证可复现。

文档同时注明:这一步"已被自动化构建步骤覆盖"(This is covered by our automated build steps),即 CI 构建产物时已经生成过该归档,这里主要是让发布经理本地留有一份与 tag 严格对应的源码包,并作为后续签名资产清单的一部分。

四、步骤三:用 grype 对容器镜像做发布前扫描

Dangerzone 的核心安全机制是把文档转换放进隔离容器,容器镜像由独立的dangerzone-image仓库构建(对应总流程的第 3 阶段)。由于镜像构建完成到真正发布之间可能已经过去了一段时间,release.md 要求在发布前对最终产出的镜像再跑一次漏洞扫描:

docker pull anchore/grype:latest docker run --rm -v ./share/container.tar:/container.tar anchore/grype:latest /container.tar

命令把本地保存的镜像 tarball(./share/container.tar)挂载进一次性 grype 容器做离线扫描,无需将镜像推送到任何 registry。这是典型的"发布前最后一道安全闸门":构建期扫描只能代表构建时刻的安全状态,发布时重扫才能覆盖中间新披露的 CVE。

五、步骤四:收集资产、计算 SHA-256 并 GPG 签名

这是整个发布阶段最核心的一步。文档要求把所有资产收集到一个目录,计算 SHA-256 哈希并签名,仓库提供了 dev_scripts/sign-assets.py 来自动化:

# Sign all the assets ./dev_scripts/sign-assets.py ~/release-assets/0.11.0/github --version 0.11.0

(原文使用$VERSION变量,此处以当前版本0.11.0展开。)结合源码,可以看清这个脚本的完整行为:

1. 资产清单是硬编码的。脚本顶部定义了必须齐备的四类资产(dev_scripts/sign-assets.py):

DZ_ASSETS = [ "Dangerzone-{version}.msi", # Windows "Dangerzone-{version}-arm64.dmg", # macOS Apple Silicon "Dangerzone-{version}-i686.dmg", # macOS Intel "dangerzone-{version}.tar.gz", # 源码归档 ]

ensure_assets_exist()会逐一检查这些文件是否存在,缺任何一个直接抛错终止——这相当于发布前的资产完整性门禁:少一个平台安装包就不允许进入签名环节。

2. 哈希文件格式兼容sha256sumhash_assets()hashlib.file_digest(f, "sha256")计算每个资产的摘要,输出{hexdigest} {filename}两空格分隔的格式(dev_scripts/sign-assets.py),与man sha256sum描述的sha256sum输出一致。这意味着用户可以一行命令校验所有下载内容:

sha256sum -c checksums-0.11.0.txt

产物写入checksums-0.11.0.txt

3. 签名策略:资产用分离签名,校验和文件用清签名。脚本对每个资产执行gpg --batch --yes --armor --detach-sig,生成独立的.asc文件(dev_scripts/sign-assets.py);唯一的例外是校验和文件本身——它对checksums文件使用--clearsign内嵌签名,然后把checksums-0.11.0.txt.asc重命名回checksums-0.11.0.txt,使校验和文件自身携带签名、保持原名发布(dev_scripts/sign-assets.py)。签名密钥指纹在脚本中固定为:

DZ_SIGNING_PUBKEY = "DE28AB241FA48260FAC9B8BAA7C9B38522604281"

即必须用 Dangerzone 官方发布私钥签名,防止误用其他密钥。

执行成功后,~/release-assets/0.11.0/github目录内将是 4 个资产 + 4 个.asc分离签名 + 1 个已清签名的checksums-0.11.0.txt,共 9 个文件,构成一次完整、可被第三方独立验证的发布物集合。

六、步骤五:批量上传到 GitHub 草稿发布

签名完成后,把所有资产上传到已经创建好的draft(草稿)Release

find ~/release-assets/0.11.0/github | xargs -n1 ./dev_scripts/upload-asset.py --token ~/token --draft

dev_scripts/upload-asset.py 的单文件上传流程从源码看有几层防御与细节:

  • 目标 Release 的三种定位方式(dev_scripts/upload-asset.py):--tag按标签名查询、--release-id直接指定、或--draft自动取最新草稿。草稿定位逻辑get_latest_draft_release()会调用 GitHub Releases API,过滤出draft状态的 release,并且若发现多于一个草稿或零个草稿都直接抛错(dev_scripts/upload-asset.py)——这避免了把资产误传到旧草稿上;
  • Token 安全管理--token参数传的是 token文件路径(如~/token),脚本读取后以Bearer头认证;不传则交互式getpass输入(dev_scripts/upload-asset.py)。此外还有一行防御性断言assert args.file != args.token,确保不会把 token 文件本身当作资产上传;
  • 上传走 GitHub 的 uploads APIPOST https://uploads.github.com/repos/freedomofpress/dangerzone/releases/{release_id}/assets?name={filename}Content-Typeapplication/octet-stream。源码注释说明了一个限制:GitHub 该端点不接受 multipart 编码,因此只能整文件读入内存后一次性 POST(dev_scripts/upload-asset.py)。

find ... | xargs -n1把目录内每个文件(资产、签名、校验和)逐一喂给脚本,即草稿 Release 上会同时挂上全部 9 个文件。上传只是草稿阶段的"填装"——此时 Release 对外不可见,可以随时补传、重传。填装完毕后,文档要求把草稿 Release 的目标从 RC 状态更新为最终的正式 git tag(即第二步推送的v0.11.0),这样公开后页面展示的 tag、下载链接与签名资产三者对齐。

七、步骤六:同步网站与 README

在公开 Release 之前,还有两个文档层面的 PR 需要先提交:

  1. 网站 PR:向 Dangerzone 官网仓库提交 PR,让下载页链接指向新版本安装包;
  2. 仓库 PR:更新本仓库 README.md,把其中"Version"及指向 INSTALL.md 安装说明的链接对齐到新版本。

这两个 PR 此时只提交、不合并——它们与后面的 packages 仓库 PR 一起,作为"发布公开瞬间"的原子操作批量合并。另外,pre-release 阶段已要求用 docs/templates/release-notes-regular.md(常规版)或 docs/templates/release-notes-security.md(安全修复版)模板写好发布说明并送审,草稿 Release 的文案即来源于此。以当前仓库为例,INSTALL.md 中已经预留了指向v0.11.0各平台下载链接的段落(macOS arm64/i686、Windows MSI),说明"链接先行、资产随后"是该项目的一贯做法。

八、📣 正式发布:六个"合并/公开"动作

文档用单独的 "Publish the release!" 小节列出公开阶段的动作清单,其设计意图是把对外的可见性变更压缩到最短时间窗内,避免"安装包已可下载但 apt 源还没更新"这类中间态:

  1. 合并packages仓库中的 PR——该仓库维护 Dangerzone 的 apt 源等软件包分发基础设施,合并后apt update && apt install dangerzone即可装到新版本;
  2. 将 GitHub 草稿 Release 置为公开;
  3. 合并官网仓库(dangerzone.rocks)与本仓库(dangerzone)中此前提交的 PR,让网站下载链接和 README 同时生效;
  4. 在 Mastodon 官方账号发布发布公告;
  5. 如有新增受支持平台,扩展check_repos.ymlCI 测试,覆盖新平台;
  6. 手动触发check_repos.ymlCI 测试并确认通过——这一步验证的是发布后各软件源/仓库中的版本确实可被 CI 检测到,是发布闭环的最终确认。

从第 2 步(公开 Release)到第 3 步(合并两个 PR)的顺序值得注意:先让 GitHub 上的资产可下载,再切换 apt 源和官网链接,能最大限度缩短"官网已指向新版本但资产 404"的窗口。

九、小结:一条签名信任链贯穿始终

release.md的所有步骤串起来看,Dangerzone 的发布流程本质上是在维护一条可独立验证的信任链:

环节产物验证手段
版本固化PGP 签名 tagv0.11.0git 签名验证 + 发布公钥
源码分发dangerzone-0.11.0.tar.gz(git archive)SHA-256 + GPG 分离签名
平台安装包.msi/.arm64.dmg/.i686.dmg同上,由sign-assets.py统一处理
容器镜像签名镜像(独立仓库构建)发布前 grype 漏洞重扫
校验和checksums-0.11.0.txt(内嵌 clearsign)sha256sum -c+ gpg 验签
软件源packages仓库 PRcheck_repos.ymlCI 验证

所有签名动作都锚定在同一个官方密钥指纹(DE28AB241FA48260FAC9B8BAA7C9B38522604281)上,草稿发布 + 最后瞬间统一合并的编排则保证了对外可见状态的一致性。对需要为多平台发行版软件设计发布流程的项目而言,docs/developer/release/ 目录下这一整套"checklist 化 + 脚本化"的实践,加上 dev_scripts/ 中可直接复用的签名与上传脚本,是一份相当完整的参考实现。

【免费下载链接】dangerzoneTake potentially dangerous PDFs, office documents, or images and convert them to safe PDFs项目地址: https://gitcode.com/GitHub_Trending/da/dangerzone

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 21:52:10

Linux 安装 PyCharm:tar.gz 解压、桌面集成与解释器配置

1. 为什么要在Linux上装PyCharm:先把选型这件事聊明白Linux下写Python,编辑器选择其实挺多的。终端里Vim配一堆插件能用,VSCode装个Python扩展也能用,但真到了要看大型项目、要跳转定义、要重构改名、要调试多线程的时候&#xff…

作者头像 李华
网站建设 2026/9/17 21:52:04

Playwright 通过 CDP 连接已登录 Chrome 实战

做自动化测试或者数据采集的朋友,大概率都撞过这堵墙:你手动打开谷歌浏览器,登录好账号、点掉一堆同意弹窗、把该过的验证都过完了,页面状态干干净净。结果 Playwright 一跑chromium.launch(),弹出来的是一个全新的窗口…

作者头像 李华
网站建设 2026/9/17 21:47:54

SQL中VALUES构造临时表的实用技巧与避坑指南

1. 从一个调试场景说起:为什么需要“临时造数据”做数据库开发的人,几乎都遇到过这种尴尬:线上有个报表逻辑要验证,但测试环境里没有合适的数据;或者要排查一条 SQL 的关联逻辑对不对,但手头只有表结构&…

作者头像 李华
网站建设 2026/9/17 21:47:52

词法分析器设计核心:从手写实现到Flex自动生成与调试技巧

简介:该资源是编译原理课程中一份完整的词法分析器设计实验报告,面向计算机及相关专业学生,用于解决C语言词法分析器的设计、编制与调试问题,帮助加深对词法分析原理的理解。报告基于C语言实现,包含SYMBOL.H、BASEDATA…

作者头像 李华