Koji Build 命令参数深度解析:从入门到精通

在 Koji 构建系统中,koji build 是最核心、最常用的命令之一。理解其各个参数的含义和应用场景,是每一位 Linux 发行版构建工程师和包维护者的必修课。本文将逐一拆解 koji build 的每个参数,并重点剖析 --scratch 参数的本质、NVR 唯一性规则,以及构建失败后的恢复策略。


一、命令基本结构

bash 复制代码
koji build [options] <target> <srpm path or scm url>

核心参数说明

  • <target> :构建目标,决定了构建根(buildroot)的内容来源以及构建产物的最终去向。需要特别注意的是,target 不同于 destination tag(构建最终落地的标签)或 build tag(构建根内容的来源标签) 。可用 koji list-targets 查看所有可用的构建目标。
  • <srpm path or scm url>:源码包路径或 SCM 仓库地址。普通用户通常需要通过 SCM 发起构建,直接从 SRPM 构建通常仅限管理员操作。

二、参数详解

1. --skip-tag

含义 :构建完成后,不尝试将构建产物自动打上目标标签。

应用场景

  • 当您希望手动控制标签行为时使用。
  • 配合后续的 koji tag-build 命令,实现更精细的发布流程控制。
  • 适用于需要先验证构建产物再决定是否正式纳入仓库的场景。

2. --scratch ⭐(核心参数)

含义 :执行草稿构建(Scratch Build) ------ 构建包但不将其打标签并入正式仓库

Scratch Build 的本质特征

特征 Scratch Build 正式构建(Real Build)
是否打标签 ❌ 否 ✅ 是
是否进入正式仓库 ❌ 否 ✅ 是
NVR 唯一性检查 ❌ 不检查 ✅ 严格检查
产物引用方式 任务 ID(Task ID) NVR(Name-Version-Release)
产物下载方式 koji download-taskkoji-download-scratch koji download-build
清理策略 自动清理(系统周期性删除) 长期保留

Scratch Build 的核心价值

  1. 快速验证:在正式提交构建前,先用 Scratch 构建验证代码是否能成功编译。
  2. 多架构测试:在无需拥有各架构硬件的情况下,测试包在各种架构上的构建情况。
  3. 无污染测试:即使构建失败,也不会在正式仓库中留下任何记录。
  4. 无 NVR 冲突:可以反复使用相同的 NVR 进行 Scratch 构建,不受唯一性限制。

典型工作流

开发者通常会先执行一系列 Scratch 构建进行测试,待一切正常后,增加 Release 号,再执行一次正式构建。

⚠️ 重要提示 :Scratch 构建虽然方便,但不能替代正式构建。Scratch 构建成功后,仍需发起一次正式构建才能真正将包纳入发行版仓库。


3. --rebuild-srpm--no-rebuild-srpm

含义 :仅用于 Scratch 构建,控制是否强制重新构建 SRPM

  • --rebuild-srpm:强制重新构建 SRPM(即使已存在)。
  • --no-rebuild-srpm:强制不重新构建 SRPM。

应用场景

  • 当您修改了 spec 文件但不想重新生成完整的 SRPM 时,可用 --no-rebuild-srpm 加速测试。
  • 当您需要确保 SRPM 是最新生成的时候,使用 --rebuild-srpm

4. --wait--nowait

含义 :控制 Koji 客户端是否等待构建任务完成后再退出。

  • --wait:等待构建完成(即使命令在后台运行)。
  • --nowait:不等待构建完成,提交后立即返回。

应用场景

  • --wait:适用于脚本和 CI/CD 流水线,需要确保构建完成后再执行后续步骤。
  • --nowait:适用于交互式场景,提交构建后可以继续做其他事情。

5. --wait-repo

含义 :等待给定 target 的实际构建根仓库(buildroot repo)准备就绪

应用场景

  • 在构建依赖链场景中,确保依赖包已进入构建根后再发起当前构建。
  • 配合 --wait-build 使用,实现复杂的构建顺序控制。

6. --wait-build=NVR

含义 :等待指定的 NVR 出现在构建根仓库中

应用场景

  • 构建顺序依赖:当前包依赖另一个包的最新版本,需要等待该包构建完成并进入仓库后再开始构建。

7. --quiet

含义不打印任务信息

应用场景

  • 在脚本中静默执行,减少日志输出。
  • 与其他命令组合使用时,避免输出干扰。

8. --arch-override=ARCH_OVERRIDE

含义覆盖构建架构列表

应用场景

  • 当 target 默认包含多个架构(如 x86_64、aarch64、ppc64le),但您只想在特定架构上测试时使用。
  • 调试特定架构的构建问题。

9. --fail-fast

含义 :覆盖 build_arch_can_fail 设置,尽可能快地失败

应用场景

  • 当您希望尽早发现构建问题,而不是等待所有架构都尝试构建完成。
  • 在 CI/CD 中加快反馈速度。

10. --repo-id=REPO_ID

含义使用指定的仓库 ID 进行构建。

应用场景

  • 高级调试场景,需要固定使用某个特定版本的仓库进行可重现构建。
  • 测试仓库变更对构建的影响。

11. --noprogress

含义不上传进度条显示

应用场景

  • 在日志记录场景中,避免进度条字符污染日志文件。

12. --background

含义以较低优先级运行构建任务

应用场景

  • 当构建系统负载较高时,将非紧急构建任务降级。
  • 大型构建(如 Kernel)在非高峰时段运行。

三、深度专题:--scratch 的本质与 NVR 唯一性

3.1 什么是 NVR?

NVR = Name-Version-Release,是 Koji 中唯一标识一个构建的三元组。

Koji 确保所有已完成的正式构建拥有唯一的 NVR。这是构建系统一致性的基石。

3.2 正式构建的 NVR 唯一性规则

规则 :Koji 不允许使用已经构建过的 NVR 再次发起正式构建。

"In koji nvrs are forever, mostly. You can rebuild over a failed or canceled build, but even a deleted build still blocks a rebuild of the same nvr."

翻译:在 Koji 中,NVR 基本上是永久性的。你可以在失败或取消的构建之上重新构建,但即使是一个已被删除的构建,仍然会阻止相同 NVR 的重新构建。

这意味着:

  • 一个 NVR 一旦被使用(无论构建成功还是失败),就不能再次用于正式构建。
  • 即使使用管理员权限删除构建记录,该 NVR 仍然被"占用"。

3.3 构建失败后的恢复策略

场景 :执行 koji build(不带 --scratch)时构建失败,能否再次启动相同 NVR 的正式构建?

答案 :❌ 不能

即使构建失败,该 NVR 已经被 Koji 记录在案。再次尝试会收到类似错误:

Package xxx-N-V-R has already been built

正确的恢复方法

方法 操作 适用场景
方法一(推荐) 增加 Release 号 (如从 1 改为 2),使用新 NVR 重新构建 所有场景,最简单可靠
方法二(高级) 使用 --skip-nvr-check 跳过 NVR 检查 需要覆盖检查的特殊场景(需谨慎)
方法三(管理员) 使用 koji call deleteBuild <nvr> 删除构建记录 仅管理员可操作,且需确保无标签引用

⚠️ 强烈建议直接增加 Release 号是最简单、最安全的方式。

3.4 Scratch Build 的 NVR 处理

Scratch Build 不受 NVR 唯一性约束

  • 可以使用任意 NVR(包括已被正式构建使用的 NVR)
  • 可以反复使用相同 NVR 进行多次 Scratch 构建
  • Scratch 构建的产物不进入正式仓库,因此不会与正式构建冲突

这正是 Scratch Build 作为"测试工具"的核心价值所在。


四、参数组合实战示例

示例 1:快速测试构建(Scratch)

bash 复制代码
koji build --scratch --wait f40-build git+https://pagure.io/mypkg.git
  • --scratch:不进入正式仓库
  • --wait:等待构建完成
  • 适用于快速验证代码是否能编译通过

示例 2:多架构调试

bash 复制代码
koji build --scratch --arch-override=aarch64 --wait f40-build ./mypkg.src.rpm
  • --arch-override=aarch64:仅构建 aarch64 架构
  • 适用于调试特定架构的构建问题

示例 3:正式发布构建

bash 复制代码
koji build --wait f40-build git+https://pagure.io/mypkg.git#main
  • 不带 --scratch:正式构建,产物进入仓库
  • 确保代码已在 Scratch 构建中验证通过

示例 4:依赖等待场景

bash 复制代码
koji build --wait-repo --wait-build=dep-pkg-1.0-1.fc40 f40-build ./mypkg.src.rpm
  • --wait-repo:等待构建根就绪
  • --wait-build:等待依赖包出现
  • 适用于复杂依赖链场景

五、总结

参数 核心作用 关键场景
--scratch 草稿构建,不进入正式仓库 测试验证、多架构调试
--skip-tag 跳过自动打标签 手动控制发布流程
--wait / --nowait 控制是否等待构建完成 脚本自动化 vs 交互式
--wait-repo / --wait-build 等待构建根或依赖包就绪 复杂依赖链场景
--arch-override 覆盖构建架构列表 单架构调试
--fail-fast 快速失败 CI/CD 快速反馈
--background 低优先级运行 非紧急大型构建
--rebuild-srpm / --no-rebuild-srpm 控制 SRPM 重建 Scratch 构建优化

黄金法则

  1. 测试用 Scratch,发布用正式构建
  2. 正式构建失败后,增加 Release 号而非重复使用相同 NVR
  3. Scratch 构建不能替代正式构建 ------ 两者各有其位,不可混淆。

本文适用于 Linux 发行版构建工程师、DevOps 系统架构师及 RPM 包维护者。