Skip to content

ROM BadZipFile 打包失败 ​

Jenkins 打包流水线报 BadZipFile: File is not a zip file,查了一圈打包脚本,最后发现脚本没问题——是 6.1.2 的打包配置读了 6.2.0 的资源目录。打包问题先查输入,再查脚本。

定位路径4 步排除
根因配置漂移
长期防线周三/五 merge

背景 ​

车机 ROM 由 Jenkins 流水线打包,出包后通过刷机工具刷到台架和实车上,是台架调试和路测的入口。当时 6.1.2 和 6.2.0 两条版本线并行开发,分支、资源目录、打包配置都是多份并存的状态——这正是配置漂移最容易发生的环境。

打包失败不是"重新跑一遍"就能糊过去的事:刷机侧对包类型有严格要求(比如刷机要选 UserDev/UserDebug 包,不能拿 Release/Alpha 包刷),一个坏包卡住的是整个验证链路。

事故时间线 ​

  1. 流水线执行到 ROM 打包步骤失败,Python zipfile 抛出 BadZipFile: File is not a zip file。
  2. 第一怀疑是打包脚本的 ZIP 生成逻辑——本地复现,正常。
  3. 第二怀疑是构建机 Python 版本差异——比对,版本一致。
  4. 回头检查输入文件,发现 6.1.2 分支的打包脚本读取的是 6.2.0 分支的资源目录。
  5. 根因确认:分支管理失误,6.1.2 的打包配置指向了 6.2.0 的资源路径。

根因 ​

直接原因一句话:

打包脚本读取资源路径:
  /build/6.2.0/resource/  ← 应该是 /build/6.1.2/resource/

6.2.0 资源目录下的文件格式变更 → 老的 ZIP 打包逻辑不兼容 → BadZipFile

深层原因是分支并行期的配置漂移:版本线多了之后,打包配置里的路径靠人肉维护,没有任何机制保证"6.1.2 的配置一定指向 6.1.2 的资源"。BadZipFile 只是漂移第一次以报错的形式冒出来,没报错的时候可能打出过内容错误的包——后者更危险。

mermaid
flowchart TD
    A["流水线报 BadZipFile"] --> B{"本地复现?"}
    B -->|"正常"| C{"Python 版本差异?"}
    C -->|"版本一致"| D["检查输入文件"]
    D --> E["6.1.2 配置指向<br>6.2.0 资源目录"]
    E --> F["资源格式已变更<br>老 ZIP 逻辑不兼容"]
    F --> G["根因:分支配置漂移"]

这个排查顺序值得保留:先排除"脚本病了",再排除"环境变了",最后才落到"喂给脚本的东西错了"。前两步各花几分钟,第三步才花值得的功夫。

止血 ​

  • 修正打包配置,资源路径指向正确的 6.1.2 目录,重跑流水线恢复出包。
  • 没有顺手"优化"打包脚本——脚本没问题,动它只会引入新变量。

长期改进 ​

  • 分支管理规则:确立每周三、五统一 merge 的节奏,避免分支长期游离、跨版本互相引用。这条规则后来沉淀进了年度 3D 分支管理文档。
  • 分支隔离:每个版本的资源目录独立,配置里不允许出现跨版本路径。
  • 版本可追溯:ROM 版本号本身带日期戳和构建信息(形如 V5.9.0.6810_20250827014627),出问题时可以反查——在内部打包平台按日期找到那次打包记录,再沿 Maven 仓库路径查到集成的应用版本和依赖库版本(例如 3D 库),快速回答"这个包里到底装了什么"。这条反查路径后来成为排查"版本不对"类问题的标准动作。

关键实现 ​

修复本身只有一行配置,值得展开的是两条后来固化的方法。

低成本假设先排除。 排查顺序刻意从便宜到贵:

假设验证方式成本结论
ZIP 生成逻辑有 bug本地复现分钟级正常,排除
构建机 Python 版本差异版本比对分钟级一致,排除
输入文件错误检查资源路径需要翻配置命中根因

打包类故障的输入面比脚本面大得多,但人总是先怀疑自己最熟的脚本。把"先查输入"写成纪律,比事后聪明有用。

版本号反查路径。 ROM 版本号里带日期戳和构建序号,反查分三步:

  1. 在内部打包平台按日期定位那次打包记录,拿到集成的应用版本号;
  2. 按应用名 + 版本号拼出 Maven 仓库路径,拿到该次构建的完整产物列表;
  3. 从依赖清单文件里确认各依赖库版本(比如 3D 库),回答"这个包和我以为的包是不是同一个"。

这条路径后来成为所有"版本不对"类问题的标准起手式——先确认包里装了什么,再谈别的。

指标 ​

  • 定位过程:4 步假设排除,前两步(本地复现、版本比对)都是几分钟级的低成本验证。
  • 修复成本:1 处配置修正,流水线当次恢复。
  • 防线产出:1 条周节奏 merge 规则 + 1 套版本号反查方法。

复盘 ​

  • 打包失败不要只查打包脚本,先查输入是否正确。 这是本次最值钱的一条经验,适用于绝大多数构建类故障:脚本是常客,输入是变量。
  • 配置漂移是 CI/CD 里最常见也最不体面的问题——没有高深的技术含量,但多发期恰好是多版本并行、大家都很忙的时候。
  • 反查能力要提前建设:版本号能反查打包记录和依赖版本,事故时就少一半猜测;不能反查,每次都在考古。
  • 多版本并行期是配置漂移的高发期,越是赶进度的阶段,越要先立分支规则再开工——这次事故发生在 6.1.2/6.2.0 并行期不是巧合。
  • 修复只动该动的那一处:配置错了就改配置,不顺手"优化"没病的脚本。止血阶段的克制,本身就是止血的一部分。

罗子初 · AI 座舱专家 · 8年端侧研发

Lv.1