Backport Builder 是一个发布工程(release-engineering)项目。它把源仓库视为输入,把生成的目录树视为输出,并把自定义 Rector 规则视为经过测试的构建逻辑。
当你维护降版规则、生成的包元数据、目标运行时检查,或围绕 nextpdf/backport-builder 的发布自动化时,请参考本指南。
| 层级 | 负责者 | 职责 | 不应放在这里的内容 |
|---|
| 源仓库 | 产品仓库 | 权威的 PHP 源代码与测试。 | 生成的降版修改。 |
| 构建脚本 | nextpdf/backport-builder | 合并源代码、执行转换、写入元数据并验证输出。 | 运行时应用程序逻辑。 |
| Rector 配置 | nextpdf/backport-builder | 针对目标的降版策略。 | 未经测试的跨目标假设。 |
| 自定义 Rector 规则 | nextpdf/backport-builder | 项目专属的语法转换。 | 未经测试的大范围改写。 |
| 生成的包 | 构建输出 | 可在较旧运行时安装的产物。 | 将其当作事实来源(source of truth)进行手动修补。 |
| 阶段 | 行为 | 开发者动作 |
|---|
| 检出来源 | 发布工作流会按目标标签检出源仓库。 | 保持各包之间的源代码引用一致。 |
| 契约验证 | ValidateBuildContract::run() 会检查构建假设。 | 将契约验证失败视为发布阻断条件。 |
| 合并 | MergeSources::run() 会组装目标包的目录树。 | 在执行 Rector 之前,先确认目标范围。 |
| 转换 | Rector 配置与自定义规则会对语法进行降版。 | 为每一次规则变更加上 fixture 测试。 |
| Composer 调整 | AdjustComposer 会写入生成的包元数据与 replace 映射。 | 验证包名称、版本、许可证与依赖限制。 |
| 运行时验证 | 生成的输出会在目标 PHP 版本上执行语法检查与测试。 | 将目标运行时失败视为发布阻断条件。 |
| 发布 | 压缩包会附加到一次发布中。 | 不要把生成的输出当作事实来源来修补。 |
| 工作项目 | 事实来源(source of truth) | 生成输出的处理策略 |
|---|
| PHP 功能使用 | 主源仓库。 | 由 backport 规则适配该功能。 |
| 依赖限制 | 源端的 composer.json 元数据,加上调整脚本。 | 生成的 composer.json 必须可重现。 |
| 语法降版 | Rector 配置与自定义规则。 | 不应手动编辑生成的源代码。 |
| 运行时支持 | 目标分支与 CI 矩阵。 | 构建必须在目标 PHP 上通过。 |
| 发布说明 | 文档与发布自动化。 | 生成的产物应链接回源版本。 |
每个自定义规则都应有明确且范围狭窄的用途、元数据和 fixture 覆盖。
| 规则方法 | 用途 | 品质要求 |
|---|
getRuleDefinition() | 为 Rector 工具记录这项转换。 | 附上一组与真实降版相符的 before/after 示例。 |
getNodeTypes() | 限定此规则要检查的 AST 节点。 | 尽量缩小节点清单。 |
refactor() | 应用该转换,或原样返回不变。 | 让无关节点保持不变,并确保行为具有决定性。 |
| fixture 测试 | 验证 before/after 输出。 | 覆盖最小有效输入,以及至少一个跳过(skip)场景。 |
final class ExampleDowngradeRector extends AbstractRector
public function getNodeTypes(): array
return [SomeNode::class];
public function refactor(Node $node): ?Node
if (!$node instanceof SomeNode) {
return $this->rewriteNode($node);
在开发期间与发布候选版本验证时使用 dry run。只有在源引用与目标分支都已确定时,才使用真实输出。
php scripts/build.php --version=2.0.0 --target=php81 --dry-run
php scripts/build.php --version=2.0.0 --target=php74 --no-pro
生成的包验证应在目标运行时上执行,而不是只在现代化的构建主机上执行。
| 扩充点 | 用途 | 限制条件 |
|---|
| Rector 配置文件 | 针对目标的降版策略。 | 保持 PHP 8.1 与 PHP 7.4 轨道相互独立。 |
| 自定义 Rector 规则 | 项目专属的语法转换。 | 必须具备元数据与 fixture 测试。 |
| Composer 调整脚本 | 生成包的标识信息。 | 版本号必须与 SemVer 保持一致。 |
| 合并脚本 | 选择并整合源包输入。 | 必须记录源根目录与输出根目录。 |
| 构建工作流 | 发布协调。 | 必须在目标运行时上验证生成的输出。 |
- 在最小 fixture 中重现不受支持的语法。
- 新增或更新一个自定义 Rector 规则。
- 为该规则添加 before/after fixture。
- 执行 dry build。
- 在目标 PHP 运行时上验证生成的输出。
- 必要时,将同一项逻辑变更应用到每一个长期维护的目标分支。
- 确保发布产物可由源标签与构建脚本重现。
| 失败情况 | 应在何处处理 | 建议的回应方式 |
|---|
| 缺少源仓库 | 契约验证或合并阶段。 | 停止构建并修正检出的输入。 |
| Rector 解析失败 | 转换阶段。 | 缩小为一个 fixture,并更新规则或配置。 |
生成的 composer.json 不一致 | Composer 调整阶段。 | 修正生成用脚本,而不是生成的元数据。 |
| 目标语法失败 | 运行时验证。 | 在转换修复完成之前阻断发布。 |
| 无法取得 Pro 来源 | 构建配置。 | 只有在公开版本确实是预期目标时,才构建公开产物。 |
| 关注项目 | 默认值 | 何时该覆写 |
|---|
| 生成的输出 | 只读产物。 | 永远不要把它当作事实来源。 |
| 分支模型 | 各自独立、长期维护的目标分支。 | 通过各自独立的拉取请求(pull request)保持变更同步。 |
| 构建主机 | 现代化的 PHP。 | 目标运行时验证仍是能否发布的依据。 |
| 自定义规则 | 规模小,并由 fixture 支撑。 | 避免没有明确 before/after 示例的大范围转换。 |
| PHP 7.4 轨道 | 除非明确支持,否则仅限 core。 | 未经目标运行时验证,不要纳入 Pro 输出。 |
- Rector 规则元数据测试会实例化每个自定义规则。
- fixture 测试会覆盖每项转换的 before/after 代码。
- dry build 会在发布作业之前先执行。
- 目标运行时的语法检查与包测试会在生成的输出上执行。
- Composer 元数据测试会断言包名称、版本、依赖限制、replace 映射与许可证。
- 构建记录包含源路径、目标路径、目标运行时、dry-run 状态以及 Pro 纳入状态。