
Hurl PPA 打包发布实战从 GPG 签名、离线 Cargo 构建到 Launchpad 推送与安装验证【免费下载链接】hurlHurl, run and test HTTP requests with plain text.项目地址: https://gitcode.com/GitHub_Trending/hu/hurl本篇指南以 Hurl 仓库 contrib/ppa/README.md 为主体完整还原 Hurl 官方维护者在 Launchpad 上构建并发布 Ubuntu PPAPersonal Package Archive的全过程涵盖 Launchpad 账号与 GPG 密钥准备、Docker 容器化构建环境、仓库精简、离线 Rust 工具链与cargo vendor依赖打包、debuild生成 Debian 源码包、dput推送以及发布后从 PPA 安装并验证 Hurl 的完整闭环。读完本文你将能够独立复刻一条可交付给 Ubuntufocal 及更新版本用户的 Hurl APT 发布流水线并理解 Hurl 官方 deb 包背后每一条命令的工程意图。一、为什么选择 PPAHurl 的 Ubuntu 分发场景Hurl 是一个用 Rust 编写的命令行工具用纯文本格式定义并执行 HTTP 请求同时可对响应做断言、捕获变量并支持 JSON/XML/XPath 查询。对 Ubuntu 用户而言相比手工编译通过apt从 PPA 安装可以自动获得依赖解析、签名校验和后续升级路径。从仓库打包配置 contrib/ppa/debian/control 可以确认官方包的基本面貌Source: hurlSection: utilsPriority: optionalBuild-Depends声明了构建依赖debhelper ( 10)、pkgconf、gcc、libclang-dev、curl、libxml2-dev、libssl-dev、python3安装产物的Architecture: any即随目标架构编译描述明确点出 Hurl 的定位runs HTTP requests defined in a simple plain text format可链式请求、捕获值并评估 header 与 body 上的查询。安装清单 contrib/ppa/debian/hurl.install 进一步揭示了最终 deb 包的组成target/release/hurl usr/bin target/release/hurlfmt usr/bin target/man/hurl.1.gz usr/share/man/man1 target/man/hurlfmt.1.gz usr/share/man/man1 debian/copyright usr/share/doc/hurl changelog.Debian.gz usr/share/doc/hurl即一个 deb 包含两个可执行文件hurl与hurlfmt、两份压缩 man page 以及版权与变更记录。整个发布流水线就是为了可靠地产出并托管这样的包。二、流水线全景一次 PPA 发布经历的阶段综合 contrib/ppa/README.md官方发布流程可以划分为十个阶段本文后续章节逐一展开前置准备Launchpad 账号、PPA 创建、GPG 公钥登记参数收集确定 Hurl 版本号、Ubuntu codename、GPG passphrase密钥导出把 GPG 公钥/私钥导出到共享目录容器构建进入指定 codename 的ubuntu:${codename}Docker 容器依赖安装安装 gpg、构建工具链与 deb 打包工具密钥导入与源码获取导入 GPG 密钥克隆对应版本的 Hurl 源码并带入 debian 配置仓库精简剔除 CI、文档、测试等与打包无关的内容离线工具链制作精简版 Rust/Cargo 离线安装包与vendor.tar.xz因为 PPA 构建机无外网debian 元数据生成cargo-checksum.json、cargo home 配置、changelog、control 修正打包、校验、推送与安装验证lintian→debuild -S→dput→ apt 安装测试。三、前置准备Launchpad 账号与 GPG 密钥发布 PPA 的第一步是拥有 Launchpad 身份并建立 GPG 信任链。官方流程包含四步操作前往 Launchpad 官网注册账号并登录在账号中创建目标 PPA例如官方使用的ppa:lepapareil/hurl将 GPG 公钥提交到 Ubuntu keyserver 并完成校验把该 GPG 公钥添加到你的 PPA此后该密钥签名的包才会被 Launchpad 接受。GPG 密钥的日常管理命令在 contrib/ppa/README.md 中以 gpg memo 形式给出是整个流程的基石# 获取 gpg_keyid列出密钥取以空格开头的行十六进制 keyid gpg_keyid$(gpg --list-keys | grep -E ^ | tr -d ) # 获取 GPG-FINGERPRINT gpg --fingerprint ${gpg_keyid} # 导出 ascii-armored 格式的公钥用于提交到 keyserver / PPA gpg --armor --export ${gpg_keyid} # 分别导出公钥与私钥用于备份或迁移 gpg --armor --export ${gpg_keyid} /tmp/mypublickey.asc gpg --armor --export-secret-keys ${gpg_keyid} /tmp/myprivatekey.asc # 导入公钥和私钥 gpg --import /tmp/mypublickey.asc gpg --import /tmp/myprivatekey.asc要点说明gpg --list-keys | grep -E ^ 过滤出 pub 行下方的 keyid通常是 40 位十六进制指纹的后 16 位或完整指纹是后续所有签名操作的标识符私钥必须妥善保管它用于对.changes等发布产物做签名公钥需要先通过 keyserver 分发再绑定到 PPAUbuntu 客户端安装时才能完成信任链校验。四、收集发布参数版本、codename 与 passphrase每次发布前交互式收集三个关键参数read -e -i -p Hurl version: hurl_version read -e -i -p Ubuntu codename: codename read -s -p Gpg passphrase: passphrasehurl_version要发布的 Git tag 名例如6.1.0必须与仓库中的 release tag 一致codename目标 Ubuntu 发行版代号如focal20.04、jammy22.04、noble24.04。README 标题明确该流程面向 Ubuntu focal and newerpassphraseGPG 私钥口令-s选项保证输入不回显。随后将 GPG 密钥以无交互方式批量导出到共享目录供容器内使用mkdir -p /tmp/gpg chmod 777 /tmp/gpg gpg_keyid$(gpg --list-keys | grep -E ^ | tr -d ) gpg --batch --passphrase ${passphrase} --pinentry-mode loopback --armor --export ${gpg_keyid} /tmp/gpg/mypublickey.asc gpg --batch --passphrase ${passphrase} --pinentry-mode loopback --armor --export-secret-keys ${gpg_keyid} /tmp/gpg/myprivatekey.asc这里的两个关键 GPG 选项值得说明--batch禁用交互提示配合脚本自动执行--pinentry-mode loopback允许通过--passphrase直接传入口令从而绕过 pinentry 图形/终端程序。五、进入目标 Ubuntu 容器构建环境隔离发布必须与目标发行版严格对应因此官方选择在对应的 Docker 镜像内完成全部构建docker run -it --rm \ --env gpg_keyid${gpg_keyid} \ --env hurl_version${hurl_version} \ --env codename${codename} \ --env passphrase${passphrase} \ --env date$(date -u %a, %d %b %Y %H:%M:%S) \ --volume /tmp/gpg:/tmp/gpg \ ubuntu:${codename} bash参数逐项解读-it交互式终端--rm退出即删除容器保证构建环境无残留通过--env注入gpg_keyid、hurl_version、codename、passphrase并把当前 UTC 时间格式化为 RFC 2822 风格date变量——这个时间稍后会写进debian/changelog--volume /tmp/gpg:/tmp/gpg把上一步导出的密钥目录挂载进容器容器内即可导入密钥镜像标签直接使用ubuntu:${codename}确保构建与目标发行版的库版本一致例如libxml2、libssl的 ABI。六、安装构建依赖进入容器后先安装用户侧工具与编译打包依赖export DEBIAN_FRONTENDnoninteractive apt update apt install -y gpg git curl wget vim xz-utils gettext moreutils pv \ apt install -y pkg-config gcc libclang-dev curl libxml2-dev libssl-dev devscripts debhelper第一组gpg密钥操作、git克隆源码、xz-utils解压 Rust 发行包、gettext提供envsubst生成 changelog、moreutils提供sponge修改 components 文件、pv管道进度显示第二组pkg-config/gcc/libclang-devRust 链接 clang 绑定需要、libxml2-dev/libssl-devHurl 的 XML 与 TLS 依赖与 contrib/ppa/debian/control 中Build-Depends一一对应、devscripts提供debuild、dput、lintian等 Debian 打包工具集、debhelperdh 构建体系。随后导入 GPG 密钥到容器export GPG_TTY$(tty) gpg --batch --passphrase ${passphrase} --pinentry-mode loopback --import /tmp/gpg/mypublickey.asc gpg --batch --passphrase ${passphrase} --pinentry-mode loopback --import /tmp/gpg/myprivatekey.ascGPG_TTY指向当前终端确保 gpg-agent 在无显示环境下能定位 tty。七、克隆源码并接入 debian 打包配置接下来按版本克隆 Hurl 源码并从 master 分支获取最新的 debian 打包配置rm -fr /tmp/ppa || true git clone --depth 1 hurl-官方仓库 --branch ${hurl_version} /tmp/ppa/hurl-${hurl_version} cd /tmp/ppa/hurl-${hurl_version}git clone --depth 1 hurl-官方仓库 /tmp/ppa/hurl-ppa cp -r ../hurl-ppa/contrib/ppa/debian .要点第一个仓库是发布目标检出与hurl_version对应的 tag第二个仓库提供的是打包配方目录即本仓库的 contrib/ppa/debian 目录其中包含 control、rules、changelog.template、cargo.config、compat、copyright、hurl.install 以及 source/format 等文件。理解这些 debian 文件是读懂打包流程的关键逐一说明control包的元数据与构建依赖声明上文已述rulesdh打包规则。本仓库中的 contrib/ppa/debian/rules 定义了三个 override 目标override_dh_clean: ./debian/bin/clean.sh dh_clean override_dh_auto_build: ./debian/bin/prerequisites.sh bin/release/release.sh gzip -9 -n --stdout CHANGELOG.md changelog.Debian.gz bin/release/man.sh可见真正的编译动作委托给了仓库的bin/release/release.sh发布脚本man page 由bin/release/man.sh生成根目录 CHANGELOG.md 会被压缩为changelog.Debian.gz放入文档目录changelog.templatechangelog 模板配合envsubst生成真实 changelog见第九节cargo.configcargo 离线源配置见第九节compat内容为10声明 debhelper 兼容级别为 10copyright完整的 Apache-2.0 许可证文本与版权声明source/format内容为3.0 (quilt)声明采用 Debian source format 3.0quilt源码包形式为.orig.tar.gz.debian.tar.xz补丁体系。八、精简仓库只保留构建所需的最小集PPA 构建机只负责编译不关心 CI、测试、编辑器配置等因此官方会删除与构建无关的目录和文件缩小上传体积并降低 lintian 噪音rm -fr .github \ .git \ rustfmt.toml \ ruff.toml \ art \ contrib \ integration \ RELEASING.md \ README.md \ CONTRIBUTING.md while read -r dir ; do rm -fr $dir done (find bin -mindepth 1 -type d | grep -Ev bin/release|bin/docs) while read -r file ; do rm -fr $file done (find bin -type f | grep -Ev man\.sh|release\.sh|build_man\.py) while read -r dir ; do rm -fr $dir done (find docs -mindepth 1 -type d | grep -v docs/manual) while read -r file ; do rm -fr $file done (find docs -type f | grep -Ev manual/)清理逻辑说明顶层删除.github、.git避免把历史与 CI 配置带入源码包、格式化配置rustfmt.toml、ruff.toml、品牌素材art、打包配方contrib、集成测试integration以及各类说明文档bin目录只保留release与docs子目录文件只保留man.sh、release.sh、build_man.py——它们正是rules中override_dh_auto_build所依赖的脚本docs目录只保留manual供man.sh生成 man page其余文档全部剔除。通过这种减法最终源码包只包含 Rust 源码、Cargo 清单、bin/release脚本与docs/manual构建面最小化。九、离线化PPA 构建机无外网下的 Rust 工具链与依赖这是整个流程中最具工程技巧的部分。PPA 构建机无法访问外网因此必须把 Rust 工具链和 crate 依赖全部搬进源码包。9.1 制作精简版 Rust/Cargo 离线安装包从 Hurl 的清单文件 packages/hurl/Cargo.toml 中读取最低 Rust 版本当前仓库为rust-version 1.98.0再针对 x86_64 与 aarch64 两个架构下载官方发行包并裁剪rust_version$(grep ^rust-version packages/hurl/Cargo.toml | cut -f2 -d) for arch in x86_64 aarch64 ; do packagerust-${rust_version}-${arch}-unknown-linux-gnu packagelight${package}-light wget https://static.rust-lang.org/dist/${package}.tar.xz xz -T0 -vd ${package}.tar.xz tar -x -f ${package}.tar dirs_to_delete$(find ${package} -type d | cut --delimiter / --field 1,2 | grep / | grep -Ev /cargo$|/rust-std-${arch}-unknown-linux-gnu$|/rustc$ | sort -u | tr \n ) rm -fr $dirs_to_delete grep -E ^cargo$|^rust-std-${arch}-unknown-linux-gnu$|^rustc$ ${package}/components | sponge ${package}/components mv ${package} ${packagelight} tar -c -f - ${packagelight} | pv ${packagelight}.tar xz -T0 -9 -v ${packagelight}.tar rm -fr ${package}.tar ${packagelight} done技巧要点仅保留cargo、rustc、rust-std-arch-unknown-linux-gnu三个必需组件其余组件目录全部删除components文件是 rustup 风格发行包的组件清单用sponge来自 moreutils原地重写只留上述三行用xz -T0 -9高压缩比重新打包为-light版本显著缩小进入源码包的体积。9.2 在容器内安装精简版工具链arch$(uname -m) packagerust-${rust_version}-${arch}-unknown-linux-gnu packagelight${package}-light tar -x -f ${packagelight}.tar.xz ./${packagelight}/install.sh --destdir/tmp/rust --disable-ldconfig export PATH/tmp/rust/usr/local/bin:$PATH rustc --version cargo --version rm -fr ${packagelight}安装到/tmp/rust而非系统目录避免污染容器基础环境--disable-ldconfig跳过 ld 缓存更新容器内无必要。9.3 cargo vendor离线依赖快照cargo vendor把Cargo.lock锁定的全部 crate 源码下载到本地vendor/目录cargo vendor tar -p -c -J -f - vendor | pv vendor.tar.xz rm -rf vendor生成的vendor.tar.xz是后续 deb 构建时cargo的离线源。从 contrib/ppa/debian/cargo.config 可以看到它的使用方式——把 crates.io 源替换为本地 vendor 目录[source.crates-io] replace-with vendored-sources [source.vendored-sources] directory vendor9.4 生成 cargo-checksum.jsonDebian 的 cargo 构建插件dh-cargo 体系需要校验 crate 包哈希。官方做法是先用cargo package生成.crate取其 sha256 写入debian/cargo-checksum.jsoncargo package --package hurl sum$(sha256sum target/package/hurl-${hurl_version}.crate | cut -d -f1 | tr -d ) echo {\package\: \${sum}\,\files\: {}} debian/cargo-checksum.json cat debian/cargo-checksum.json rm -fr target9.5 组装 cargo home 配置mkdir -p debian/cargo_home cp Cargo.toml debian/cargo_home/config { cat .cargo/config.toml echo cat debian/cargo.config } .cargo/config这里把项目自身的.cargo/config.toml与离线源配置debian/cargo.config合并为最终的.cargo/config同时把 Cargo.toml 复制为debian/cargo_home/config构建时 cargo 会在该目录寻找全局配置。十、生成 debian 元数据与源码包10.1 生成 changelog利用envsubst将 contrib/ppa/debian/changelog.template 中的变量替换为真实值envsubst debian/changelog.template debian/changelog cat debian/changelog模板内容为hurl (${hurl_version}0${codename}) ${codename}; urgencymedium * New upstream release. -- lepapareil filipe.pintoorange.com ${date} 0200其中${hurl_version}、${codename}、${date}来自第四节容器启动时注入的环境变量。生成的版本号形如hurl (6.1.00noble) noble0${codename}后缀确保本地版本号低于 Launchpad 构建出的版本便于后续上传。10.2 修正 Ubuntu 24 之前的 pkgconf 差异ubuntu_major_version$(cat /etc/lsb-release | grep DISTRIB_RELEASE | cut -d -f2 | cut -d. -f1) if [[ $ubuntu_major_version -lt 24 ]] ; then sed -i s/pkgconf/pkg-config/g debian/control fipkgconf从 Ubuntu 24.04 起才成为系统默认的 pkg-config 实现对 24 之前的发行版focal/jammy需要把 control 中Build-Depends的pkgconf改回pkg-config保证依赖可解析。10.3 lintian 检查与 debuild 生成源码包hurl_long_version$(head -1 debian/changelog | cut -d( -f2 | cut -d) -f1) cd .. tar --excludehurl-${hurl_version}/debian -c -z -f - hurl-${hurl_version} | pv hurl_${hurl_long_version}.orig.tar.gz cd hurl-${hurl_version} lintian -i -E --profile debian --display-info --display-experimental --suppress-tags source-is-missing yes | debuild -S -sa -k${gpg_keyid} -pgpg --batch --passphrase ${passphrase} --pinentry-mode loopback分步解读从 changelog 首行提取完整版本号含0${codename}后缀生成上游原始源码包hurl_long_version.orig.tar.gz——这是3.0 (quilt)格式所要求的原始 tarball并显式排除debian/目录运行lintian做静态质量检查--profile debian指定 Debian 专用 profile--suppress-tags source-is-missing忽略源码缺失告警因为 vendor 与 Rust 工具链已内嵌debuild -S仅构建源码包source package-sa强制包含 orig.tar.gz-k指定签名密钥-p指定签名程序——这里直接用gpg --batch --passphrase ... --pinentry-mode loopback实现免交互签名。随后确认产物cd .. ls -l hurl_*十一、推送 PPA 与清理11.1 dput 上传dput ppa:lepapareil/hurl hurl_*_source.changesdput读取.changes文件内含签名与文件清单把源码包上传到指定的 Launchpad PPA。_source.changes后缀表明这是源码包上传Launchpad 会在自己的构建农场中完成二进制编译与签名。11.2 清理构建产物rm -fr hurl_${hurl_version}*删除本地生成的源码包与中间产物避免污染下一次发布。至此一个 Hurl 版本即完成从源码到 PPA 的旅程。十二、发布后验证从 PPA 安装并冒烟测试发布完成后官方 README 给出了一套完整的验证流程可以在干净容器中执行。12.1 准备测试容器echo -n hurl_version read -r hurl_version echo -n Ubuntu codename read -r codename docker run -it --rm --env hurl_version${hurl_version} --env codename${codename} --volume /tmp:/tmp ubuntu:${codename} bash12.2 添加 PPA 并安装指定版本export DEBIAN_FRONTENDnoninteractive yes | unminimize # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1550DC447B95F03B apt install -y git sudo man-db curl software-properties-common \ apt-add-repository -y ppa:lepapareil/hurl \ apt list --all-versions hurl \ apt install -y hurl${hurl_version}*要点unminimize恢复精简镜像中被裁剪的 man 文档等便于验证 man pageapt-add-repository自动写入 sources.list 并导入 Launchpad 的 PPA 签名密钥被注释的apt-key adv是旧式手动导入的替代方案新流程不需要apt list --all-versions hurl列出 PPA 中所有可用版本apt install hurl${hurl_version}*精确安装刚发布的版本*通配符兼容0${codename}后缀。12.3 校验版本与 man pagehurl --version hurlfmt --version man hurl | head -1 man hurlfmt | head -1这四条命令分别验证两个二进制、两个 man page 均已正确安装。注意hurl --version的输出风格与curl --version类似参见源码 packages/hurl/src/http/version.rs 的注释可用作版本核对基准。12.4 冒烟测试从 STDIN 与从文件运行从标准输入直接运行 Hurl 测试echo -e GET https://hurl.dev\n\nHTTP 200 | hurl --test --color写入文件后运行echo -e GET https://hurl.dev\n\nHTTP 200 /tmp/test.hurl hurl --test --color /tmp/test.hurl两条命令等价地验证了 Hurl 对https://hurl.dev返回 HTTP 200 的断言--test进入测试模式失败时返回非零退出码--color开启彩色输出。这组测试与仓库集成测试例如 integration/hurl/tests_ok/hello 中的冒烟用例互相印证确认发布的二进制具备完整功能。十三、附在 Ubuntu 上重建指定版本 libxml2若目标发行版的libxml2版本过低Hurl 要求不低于2.9.11官方还提供了就地重建 libxml2 并接入 PKG_CONFIG 的脚本minimum_version2.9.11 libxml2_installed_version$(apt list --installed 2/dev/null | grep libxml2 | cut --delimiter --field 2 | cut --delimiter --field 1) if dpkg --compare-versions ${libxml2_installed_version} ge ${minimum_version} ; then echo ok else tar xf libxml2-${minimum_version}.tar.gz cd libxml2-${minimum_version} ./configure --prefix/opt/libxml2-${minimum_version} --with-zlib make -j$(nproc) make install export PKG_CONFIG_PATH/opt/libxml2-${minimum_version}/lib/pkgconfig:$PKG_CONFIG_PATH export LD_LIBRARY_PATH/opt/libxml2-${minimum_version}/lib:$LD_LIBRARY_PATH export PATH/opt/libxml2-${minimum_version}/bin:$PATH fi脚本先比较已装版本与2.9.11不足时才从源码构建到/opt/libxml2-2.9.11并导出PKG_CONFIG_PATH/LD_LIBRARY_PATH/PATH让后续编译链接到新版。这与 contrib/ppa/debian/control 中libxml2-dev的Build-Depends声明形成呼应——不同 Ubuntu 版本自带的 libxml2 能力不同必要时需要统一基线。十四、注意事项与可复用要点版本与发行版强绑定changelog 的版本号、Docker 镜像 tag、control中的依赖都围绕hurl_version与codename展开发布前务必确认三者一致GPG 是信任链核心公钥需先登记到 keyserver 并绑定 PPA私钥全程通过--batch --pinentry-mode loopback免交互使用注意保护 passphrase离线化是 PPA 构建的前提vendor.tar.xz、-light版 Rust 工具链、cargo-checksum.json三者缺一不可缺失任一环节 Launchpad 构建农场都会因无外网而失败校验先行lintian静态检查、debuild签名、dput推送、安装后--version/--test冒烟测试构成完整的质量闭环本文第十二节的验证流程可直接复制为发布检查清单配置即文档本仓库 contrib/ppa/debian 目录下的所有文件control、rules、changelog.template、cargo.config、compat、copyright、hurl.install、source/format都是理解与复刻这一发布流水线的最佳参照物contrib/ppa/README.md 则是其可执行的逐步操作手册。通过上述流程任何维护者都可以把 Hurl或其他 Rust 项目的某个版本可靠地交付给 Ubuntu focal 及更新版本的 apt 用户并获得与官方包一致的签名、版本管理和安装体验。【免费下载链接】hurlHurl, run and test HTTP requests with plain text.项目地址: https://gitcode.com/GitHub_Trending/hu/hurl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考