跳转到内容

NextPDF Backport Builder 故障排查

构建工具,而不是运行时依赖包。本页列出的每个症状都属于维护者或 CI 主机上的构建期状况。这些状况不会出现在下游应用程序中。

构建会按顺序执行五个阶段。它会在第一个失败点停止,并输出阶段名称和信息。先查看对应阶段,再到下方定位原因。五个阶段分别是合并来源、执行 Rector 降级、生成 composer.json、复制静态资产和验证输出。已对照 scripts/build.phprun()step())验证。

合并阶段会在复制之前验证每个预期的来源仓库。若有仓库缺失,它会带着缺失仓库的名称和路径中止。PHP 8.1 目标预期包含 nextpdfnextpdf-Artisannextpdf-compat-legacynextpdf-Laravelnextpdf-Symfonynextpdf-CodeIgniter;纳入 Pro 时还包括 nextpdf-Pro。PHP 7.4 目标仅预期 nextpdf。已对照 scripts/merge-sources.phprun() 验证循环、__construct() 仓库映射表)验证。

解决方式:将这些仓库以同级目录的形式检出到传入 --source-dir 的路径下,并使用上述确切的目录名称。试运行(dry-run)会列出它将读取的每个仓库。可以先用它确认布局,再执行完整构建。

协调器会报告 Rector failed on <label> (exit code: N) 并停止。该标签会指出失败发生在哪个阶段——public packagepro packageenum pre-processingfull downgrade。已对照 scripts/build.phprunRectorPass())验证。

枚举默认值触发默认参数解析器崩溃(PHP 7.4)

标题为“枚举默认值触发默认参数解析器崩溃(PHP 7.4)”的章节

这也是 PHP 7.4 目标采用两遍处理的原因。Rector 的默认参数值解析器在遇到作为构造函数提升默认值的枚举 case 时会崩溃。第 1 阶段(rector-php74-enums.php)会先把枚举转换为常量列表类。这样第 2 阶段的完整流程就永远不会看到枚举 case 默认值。如果你绕过协调器,直接对带有枚举的源代码执行完整的 PHP 7.4 配置,就会触发这个崩溃。已对照 scripts/build.phprunRector() 注解与两遍顺序)与 rector/config/rector-php74-enums.php 验证。

rector-php81.phprector-php74.php 会跳过 */tests/Benchmark/*。那些脚本引用了 Rector 无法解析的外部 PDF 函数库,因而使默认参数解析器崩溃。如果某个基准测试路径被处理,说明跳过用的通配符模式缺失,或路径不同。已对照 withSkip() 调用验证。

rector-php74.php 会跳过 DowngradeHashAlgorithmXxHashRector。那条内置规则在遇到 xxHash 常量时会崩溃。源代码并未使用 xxHash,因此跳过是安全的。已对照 rector/config/rector-php74.phpwithSkip())验证。

这些修正会在两个阶段之间执行。它们会改写枚举转类规则留下的模式。如果 PHP 7.4 输出中仍出现涉及 EnumClass::Case->value->name、以实例方法调用的原枚举方法,或在未解析类型上使用命名实参的解析错误,说明修正没有匹配到该模式。clone-with 的限制同样适用:实参匹配并非递归,因此带有嵌套括号的覆盖值不会被改写。已对照 scripts/build.phppostProcessFixups()fixEnumMethodCallSites()applyFixups())与 rector/rules/DowngradeCloneWithRector.php(记载于文件的限制)验证。

这个阶段会把处理后的 src/tests/ 从构建临时目录移动到输出目录。随后写入生成的 composer.json。此处的失败几乎都属于文件系统问题:输出目录不可写,或因为 Rector 没有产出任何内容而导致构建临时树缺失。已对照 scripts/build.phpadjustComposer()moveTree())验证。

这个阶段会从核心来源仓库复制 LICENSE,并写入生成的 CHANGELOG.md。当授权文件不存在时,复制会被静默跳过,构建继续进行;变更记录则始终会写入。此处的失败表示输出目录在构建过程中变为不可写。已对照 scripts/build.phpcopyStaticAssets())验证。

「找不到输出的 src/ 目录」/「在输出中找不到 PHP 文件」

标题为“「找不到输出的 src/ 目录」/「在输出中找不到 PHP 文件」”的章节

验证需要一个非空的 output/src。空目录树表示合并没有复制任何内容,或文件移动失败。已对照 scripts/build.phpvalidateOutput())验证。

「语法验证:已略过(需要 PHP 运行时)」

标题为“「语法验证:已略过(需要 PHP 运行时)」”的章节

这是预期内的情况,并非错误。构建主机运行的是现代版 PHP,而非目标版本,因此本机阶段只会统计文件数量,并输出用于真正语法检查的 Docker 指令。具权威性的语法门禁是发行工作流中构建后的 php -l 步骤,它会在实际的目标运行时下执行。已对照 scripts/build.phpvalidateOutput())与 .github/workflows/build.yml(PHP 8.1/PHP 7.4 语法检查步骤)验证。

这些限制是降级方案本身固有的。已对照各规则和项目 README.md 中的「Known Limitations」验证:

  • 只读属性会被移除。 readonly 会被去掉,以便 clone-with 展开的显式属性赋值在较旧的运行时上合法。降级后的输出中,运行时不再强制不可变性。
  • 在 PHP 8.1 上不会强制应用 #[Override] 该属性可能仍会保留,但较旧的运行时不会对其执行任何操作。
  • PHP 7.4 目标仅包含核心。 框架适配器、tcpdf 兼容层及 Pro 并不属于 PHP 7.4 分发版的一部分,这由构建脚本的结构决定。
  • Pro 是独立包且仅限 PHP 8.1。 没有 PHP 7.4 的 Pro 构建。
  • clone-with 实参匹配并非递归。 包含嵌套括号的覆盖值不会被转换,并且只有字符串数组键会被解析为属性名称。
  • /integrations/backport/configuration/ — 规则与标志参考。
  • /integrations/backport/production-usage/ — CI 门禁与发布通道。